Frage

I have 2 views, MainActivity and UnitActivity. In main activity there are some buttons and when user clicks on them I want to bring uo UnitActivity.

In UnitActivity layout file there are some views like TextView. For example, if the user clicks on a button called btn_marine I want to fill the layout with information about marine (a unit in starcraft game, if you know :P).

So my idea is to when user click on button of each unit I fill the text and images of the UnitActivity layout with the information I have about that unit.

At the moment I am trying to hard code this I mean before starting the intent, and I have events for buttons in OnCreate method of MainActivity:

Button btn_marine = (Button) findViewById(R.id.btn_unit_marine);
btn_marine.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {

        Intent intent = new Intent(MainActivity.this, UnitActivity.class);
        TextView unitNameView = (TextView) findViewById(R.id.textViewUnitName);
        unitNameView.setText("Marine!"); //this is line 28 with error
        startActivity(intent);
    }
});

But as soon as I click the button application exits with this error in logcat:

07-29 14:56:03.906  12696-12696/com.eetutorials.terranmate E/AndroidRuntime: FATAL EXCEPTION: main
        java.lang.NullPointerException
        at com.eetutorials.terranmate.MainActivity$1.onClick(MainActivity.java:28)
        at android.view.View.performClick(View.java:4204)
        at android.view.View$PerformClick.run(View.java:17355)
        at android.os.Handler.handleCallback(Handler.java:725)
        at android.os.Handler.dispatchMessage(Handler.java:92)
        at android.os.Looper.loop(Looper.java:137)
        at android.app.ActivityThread.main(ActivityThread.java:5041)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:511)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
        at dalvik.system.NativeStart.main(Native Method)

So my question is what is the problem in my code, and also, what you think is the best way to do such thing? I tried to create a Unit class that holds information about each unit but I dont know how can I fill the Intent from that class.

I mean how can I pass that class to UnitActivity so the views automatically gets populated?

This is for example Unit class I wanted to make:

public class Unit
{
    private String Name;
    private String HitPoint;
    private String Armor;
    private DamageModifiers DamageModifier;
    private String BaseDamage;
    private String Description;

    public String getName() {
        return Name;
    }

    public void setName(String name) {
        Name = name;
    }

    public String getHitPoint() {
        return HitPoint;
    }

    public void setHitPoint(String hitPoint) {
        HitPoint = hitPoint;
    }

    public String getArmor() {
        return Armor;
    }

    public void setArmor(String armor) {
        Armor = armor;
    }

    public DamageModifiers getDamageModifier() {
        return DamageModifier;
    }

    public void setDamageModifier(DamageModifiers damageModifier) {
        DamageModifier = damageModifier;
    }

    public String getBaseDamage() {
        return BaseDamage;
    }

    public void setBaseDamage(String baseDamage) {
        BaseDamage = baseDamage;
    }

    public String getDescription() {
        return Description;
    }

    public void setDescription(String description) {
        Description = description;
    }
}
War es hilfreich?

Lösung

Alright so the thing is, you can't edit a view if you haven't set your layout. Thats where you're nullpointer is coming from; your current Layout doesn't have the textView you're looking for.

What you can do, is pass through your info through an intent to the new activity and switch it there

Button btn_marine = (Button) findViewById(R.id.btn_unit_marine);
btn_marine.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {

        Intent intent = new Intent(MainActivity.this, UnitActivity.class);
        intent.putExtra("unitType","marine")
        startActivity(intent);
    }
});

And in your next activity's onCreate, after you set the layout:

 Bundle extras = getIntent().getExtras();
 String unitType = extras.getString("unitType");
 if (unitType.equals("marine")) {
 TextView unitNameView = (TextView) findViewById(R.id.textViewUnitName);
    unitNameView.setText("Marine!");
 }

etc etc.

Its rough, because passing it as a string is a bad idea (pass it as a switchable object, theres tons of units man!), and put the view switching in its own function / class so you don't clutter up your onCreate(). But the general logic of passing things through in Android is here, you can figure out the rest :)

Andere Tipps

You can't do it this way. You are trying to access Views in a different layout. You can't update the Views until you have inflated the layout such as calling setContentView() in your next Activity.

What you can do is make the variables in Unit.java as static variables then set them when the button is clicked so something like in MainActivity

public void onClick(View view) {

    Intent intent = new Intent(MainActivity.this, UnitActivity.class);
    Unit.Name = "Marine!";
    startActivity(intent);
}

then in UnitActivity

public void onCreate(...)
{
     super....
     setContentView(...);
     TextView unitNameView = (TextView) findViewById(R.id.textViewUnitName);
     String name = Unit.Name;
      unitNameView.setText(name);

So your Unit.java would look more like

    public class Unit
{
    public static String Name;
    public static String HitPoint;
    public static String Armor;
    public DamageModifiers DamageModifier;
    public static String BaseDamage;
    public static String Description;

And get rid of most of your getters/setters and access the variable values statically and it will be faster. Also note that static variables can be destroyed by the OS if it needs memory but going from one Activity to the next and getting the data will be fine.

You have a NullPointerException because your button is in UnitActivity layout. I think the best way to achieve what you want to do (pass a class to the other activity) is to use the android parcelable.

You implement parcelable in you class like this (How can I make my custom objects Parcelable?) :

public class Unit implements Parcelable{
    private String atrribute1;
    ...
    ...
    // Constructor
    public Unit(String attribute1,...){
        this.attribute1 = attribute1;
   }
   // Getter and setter methods
   .........
   .........

   // Parcelling part
   public Unit(Parcel in){
       String[] data = new String[3];

       in.readStringArray(data);
       this.attribute1 = data[0];
       ... = data[1];

   }

   @Оverride
   public int describeContents(){
       return 0;
   }

   @Override
   public void writeToParcel(Parcel dest, int flags) {
       dest.writeStringArray(new String[] {this.attribute1,...});
   }
   public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
       public Unit createFromParcel(Parcel in) {
           return new Unit(in); 
       }

       public Unit[] newArray(int size) {
           return new Unit[size];
       }
   };

}

You will be able to do something like this in your MainActivity:

intent.putExtra("Unit", new Unit("something",...));

and retrieve it like that in your UnitActivity

Bundle data = getIntent().getExtras();
Unit unit = (Unit) data.getParcelable("Unit");
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top