EXTRA with parcelable comes out NULL but without i

2019-08-01 06:31发布

I am getting a bit frustrated with an issue that I cannot seem to fully understand.

I have a listview with items and when I click them I want to pass an object (Parcelable) to a new activity. This is the code below:

lv_Entries.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            Intent getItchesScreen = new Intent(Home.this, Itches.class);

            getItchesScreen.putExtra("i", 3);

            Entry e = entries.get(position);

            getItchesScreen.putExtra("entry", e);

            startActivity(getItchesScreen);
        }
    });

Now, I have the "i" extra there for debugging purposes. I was just sending "entry" and when I got the intent on the activity it didn't work. Code below:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_itches);

    tv_date = (TextView) findViewById(R.id.tv_date);

    Bundle b = getIntent().getExtras();

    entry = b.getParcelable("entry");

    tv_date.setText(entry.getDate());

    itches = entry.getItches();

    itchesAdapter = new ItchAdapter(this, itches);

    ListView lv_Itches = (ListView) findViewById(R.id.lv_itches);

    lv_Itches.setAdapter(itchesAdapter);
}

So when I read my bundle there is nothing at all. No "entry" key and no "i" key (I debugged to read i using watch feature)

BUT! If I don't send "entry" and only send "i" and I debug to catch "i" I do get it!

I have no idea why sending entry is ruining things but I cannot find any answer. I debugged the object and it does find it though .get(position).

Hope anyone can give me any ideas, and sorry for any trouble.

EDIT

Below is the code for Entry:

public class Entry implements Parcelable{

private String date;
private ArrayList<Itch> itches;

public Entry(String date){
    this.date = date;
    itches = new ArrayList<Itch>();
}

// PARCELABLE
public Entry(Parcel source){
    date = source.readString();
    source.readTypedList(itches, Itch.CREATOR);
}

public void AddItch(Itch itch){
    itches.add(itch);
}

// get intensity average for the itches
public int IntensityAverage(){

    int intensity = 0;

    for(Itch i : itches){
        intensity += i.getIntensity();
    }

    return intensity/itches.size();
}

public String getDate() {
    return date;
}

public void setDate(String date) {
    this.date = date;
}

public ArrayList<Itch> getItches() {
    return itches;
}

public void setItches(ArrayList<Itch> itches) {
    this.itches = itches;
}

@Override
public int describeContents() {
    return 0;
}

@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeString(date);
    dest.writeTypedList(itches);
}

public static final Parcelable.Creator<Entry> CREATOR =
    new Parcelable.Creator<Entry>() {
        public Entry createFromParcel(Parcel source) {
            return new Entry(source);
        }

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

}

Itch class is also Parceable. I am populating correctly (no crashes on Android at least) the ListView with it.

For convenience I place the code here aswell:

public class Itch implements Parcelable{

private String time;
private String local;
private int intensity;

public Itch(String time, String local, int intensity){
    this.time = time;
    this.local = local;
    this.intensity = intensity;
}

// PARCELABLE
public Itch(Parcel source){
    time = source.readString();
    local = source.readString();
    intensity = source.readInt();
}

public String getTime() {
    return time;
}

public void setTime(String time) {
    this.time = time;
}

public String getLocal() {
    return local;
}

public void setLocal(String local) {
    this.local = local;
}

public int getIntensity() {
    return intensity;
}

public void setIntensity(int intensity) {
    this.intensity = intensity;
}

@Override
public int describeContents() {
    return 0;
}

@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeString(time);
    dest.writeString(local);
    dest.writeInt(intensity);
}

public static final Parcelable.Creator<Itch> CREATOR =
    new Parcelable.Creator<Itch>() {
        public Itch createFromParcel(Parcel source) {
            return new Itch(source);
        }

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

}

2条回答
祖国的老花朵
2楼-- · 2019-08-01 06:45

Alright so... What was the problem? Simple.

The reason why the parcelable always came out null was because a stupid error was occurring. Which error?

Well, okay so take a look at this piece of code:

entry = b.getParcelable("entry");

What is it saying? It is saying that entry will be equal to the parcelable "entry" key. But what does that really mean? Look at entry constructor.

// PARCELABLE
public Entry(Parcel source){
    date = source.readString();
    source.readTypedList(itches, Itch.CREATOR);
}

So when you say that entry is equals to a parcelable, then you will call this constructor in the Entry class that I have posted. But why is it wrong you might ask?

Well, so take a look. We're giving ArrayList itches to the method readTypeList. but... wait a second. If that is a constructor that means that we're building from 0... So... is itches initiated? No it is not! Because I was only initiating itches in the "normal" constructor!

public Entry(String date){
    this.date = date;
    itches = new ArrayList<Itch>();
}

So the solution is...

// PARCELABLE
public Entry(Parcel source){
    date = source.readString();

    //add this if condition!
    if (itches == null) {
        itches = new ArrayList<Itch>();
    }

    source.readTypedList(itches, Itch.CREATOR);
}

And thats it. That fixes our problem! :)

If other error occurs please be aware: Make SURE that your key is correct. So check out for any typos in your getting extras.

entry = b.getParcelable("entyr");

as instead of

entry = b.getParcelable("entry");

And any other type of error like that.

That is not a good practive, you should have a variable that has the "entry" written on it so you never have this type of error mistakes. I have it in my code because I am fast-programming to build up a prototype :)

Happy coding!

查看更多
Explosion°爆炸
3楼-- · 2019-08-01 06:45

have you tried doing this in onCreate()

Intent i = getIntent();
    if(i.hasExtra("entry")){
        entry = i.getParcelableExtra("entry");
    }else{
      Log.v("EXTRAS", "entry not found");
    }
查看更多
登录 后发表回答