I am trying to pass an ArrayList of objects from one activity to another using the Parcelable interface, but am consistently getting a NullPointerException when I enter the activity to which I am passing my ArrayList.
Vitamin.java - defines an object with a string and two String[] arrays, implements Parcelable
HealthBenefits.java - Displays a list of strings. When a string is selected, the list of Vitamin objects is searched and the objects containing the selected string are put into another ArrayList. This ArrayList is then passed via putParcelableArrayListExtra to the VitaminDisplay activity.
VitaminDisplay.java - Displays a list of strings corresponding to the names of the vitamins which are passed to the activity.
Vitamin.java
public class Vitamin implements Parcelable{
String theName;
String[] theFoods, theBenefits;
public Vitamin(String name, String[] benefits, String[] foods)
{
theName = name;
theBenefits = benefits;
theFoods = foods;
}
private Vitamin(Parcel in){
theName = in.readString();
ArrayList<String> tempBenefits = new ArrayList<String>();
tempBenefits = (ArrayList<String>) in.readSerializable();
ArrayList<String> tempFoods = new ArrayList<String>();
tempFoods = (ArrayList<String>) in.readSerializable();
//convert from ArrayList<String> to String[]
theBenefits = new String[tempBenefits.size()];
theFoods = new String[tempFoods.size()];
theBenefits = tempBenefits.toArray(theFoods);
theFoods = tempFoods.toArray(theFoods);
}
public String getName(){
return theName;
}
public String[] getBenefit(){
return theBenefits;
}
public String[] getFoods(){
return theFoods;
}
@Override
public int describeContents() {
// TODO Auto-generated method stub
return 0;
}
@Override
public void writeToParcel(Parcel out, int flags) {
// TODO Auto-generated method stub
out.writeString(theName);
out.writeStringArray(theBenefits);
out.writeStringArray(theFoods);
}
public static final Parcelable.Creator<Vitamin> CREATOR = new Parcelable.Creator<Vitamin>() {
public Vitamin createFromParcel(Parcel in) {
return new Vitamin(in);
}
public Vitamin[] newArray(int size) {
return new Vitamin[size];
}
};
}
HealthBenefits.java
public class HealthBenefits extends Activity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.health_benefits_layout);
ListView benefits = (ListView) findViewById(R.id.listView1);
benefits.setTextFilterEnabled(true);
ArrayAdapter<CharSequence> aa = ArrayAdapter.createFromResource(this, R.array.benefits, android.R.layout.simple_list_item_1);
benefits.setAdapter(aa);
final ArrayList<Vitamin> vitamins = new ArrayList<Vitamin>();
String[] foods1 = {"Pork", "Whole grain", "Legumes", "Nuts and seeds"};
String[] vitaBenefits1 = {"Improve nerve function", "Improve metabolism"};
vitamins.add(new Vitamin("Vitamin B1", vitaBenefits1, foods1));
String[] vitaBenefits13 = {"Improve circulatory function"};
String[] foods13 = {"Leafy green vegetables"};
vitamins.add(new Vitamin("Vitamin K", vitaBenefits13, foods13));
//...more vitamin objects added to the list, omitted for brevity
benefits.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// When clicked, show a toast with the TextView text
ArrayList<Vitamin> listToDisplay = new ArrayList<Vitamin>();
if(position == 1)
{
//code specific to first list item
for(int i = 0;i < vitamins.size();i++){
if(vitamins.get(i).getBenefit().equals("Improve immune system")) {
listToDisplay.add(vitamins.get(i));
}
}
Intent myIntent = new Intent(view.getContext(), VitaminDisplay.class);
myIntent.putParcelableArrayListExtra("VITAMINS", listToDisplay);
startActivityForResult(myIntent, 0);
}
if(position == 2)
{
//code specific to 2nd list item
}
}
});
}
}
VitaminDisplay.java
public class VitaminDisplay extends Activity{
ArrayList<Vitamin> vitaminsList;
ArrayList<String> displayList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.health_benefits_layout);
vitaminsList = getIntent().getExtras().getParcelableArrayList("VITAMINS");
displayList = new ArrayList<String>();
for(int i = 0;i < vitaminsList.size();i++){
displayList.add(vitaminsList.get(i).getName());
Log.d("VitaminDisplay", vitaminsList.get(i).getName());
}
//displayList = new ArrayList<String>();
//displayList.add("test");
ListView benefits = (ListView) findViewById(R.id.listView1);
benefits.setTextFilterEnabled(true);
ArrayAdapter<String> aa = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, displayList);
benefits.setAdapter(aa);
}
}
I believe the exception may be from how I have implemented the Parcelable class in Vitamin.java, but I have yet to find a solution. Any suggestions?
Here's the full logcat:
E/AndroidRuntime(1958): FATAL EXCEPTION: main
04-21 21:55:08.963: E/AndroidRuntime(1958): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.heartsmart/com.example.heartsmart.VitaminDisplay}: java.lang.NullPointerException
04-21 21:55:08.963: E/AndroidRuntime(1958): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2180)
04-21 21:55:08.963: E/AndroidRuntime(1958): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230)
04-21 21:55:08.963: E/AndroidRuntime(1958): at android.app.ActivityThread.access$600(ActivityThread.java:141)
04-21 21:55:08.963: E/AndroidRuntime(1958): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)
04-21 21:55:08.963: E/AndroidRuntime(1958): at android.os.Handler.dispatchMessage(Handler.java:99)
04-21 21:55:08.963: E/AndroidRuntime(1958): at android.os.Looper.loop(Looper.java:137)
04-21 21:55:08.963: E/AndroidRuntime(1958): at android.app.ActivityThread.main(ActivityThread.java:5041)
04-21 21:55:08.963: E/AndroidRuntime(1958): at java.lang.reflect.Method.invokeNative(Native Method)
04-21 21:55:08.963: E/AndroidRuntime(1958): at java.lang.reflect.Method.invoke(Method.java:511)
04-21 21:55:08.963: E/AndroidRuntime(1958): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
04-21 21:55:08.963: E/AndroidRuntime(1958): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
04-21 21:55:08.963: E/AndroidRuntime(1958): at dalvik.system.NativeStart.main(Native Method)
04-21 21:55:08.963: E/AndroidRuntime(1958): Caused by: java.lang.NullPointerException
04-21 21:55:08.963: E/AndroidRuntime(1958): at java.io.ByteArrayInputStream.<init>(ByteArrayInputStream.java:60)
04-21 21:55:08.963: E/AndroidRuntime(1958): at android.os.Parcel.readSerializable(Parcel.java:2139)
04-21 21:55:08.963: E/AndroidRuntime(1958): at com.example.heartsmart.Vitamin.<init>(Vitamin.java:23)
04-21 21:55:08.963: E/AndroidRuntime(1958): at com.example.heartsmart.Vitamin.<init>(Vitamin.java:20)
04-21 21:55:08.963: E/AndroidRuntime(1958): at com.example.heartsmart.Vitamin$1.createFromParcel(Vitamin.java:62)
04-21 21:55:08.963: E/AndroidRuntime(1958): at com.example.heartsmart.Vitamin$1.createFromParcel(Vitamin.java:1)
04-21 21:55:08.963: E/AndroidRuntime(1958): at android.os.Parcel.readParcelable(Parcel.java:2103)
04-21 21:55:08.963: E/AndroidRuntime(1958): at android.os.Parcel.readValue(Parcel.java:1965)
04-21 21:55:08.963: E/AndroidRuntime(1958): at android.os.Parcel.readListInternal(Parcel.java:2235)
04-21 21:55:08.963: E/AndroidRuntime(1958): at android.os.Parcel.readArrayList(Parcel.java:1655)
04-21 21:55:08.963: E/AndroidRuntime(1958): at android.os.Parcel.readValue(Parcel.java:1986)
04-21 21:55:08.963: E/AndroidRuntime(1958): at android.os.Parcel.readMapInternal(Parcel.java:2226)
04-21 21:55:08.963: E/AndroidRuntime(1958): at android.os.Bundle.unparcel(Bundle.java:223)
04-21 21:55:08.963: E/AndroidRuntime(1958): at android.os.Bundle.containsKey(Bundle.java:271)
04-21 21:55:08.963: E/AndroidRuntime(1958): at com.example.heartsmart.VitaminDisplay.onCreate(VitaminDisplay.java:23)
04-21 21:55:08.963: E/AndroidRuntime(1958): at android.app.Activity.performCreate(Activity.java:5104)
04-21 21:55:08.963: E/AndroidRuntime(1958): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)
04-21 21:55:08.963: E/AndroidRuntime(1958): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2144)
04-21 21:55:08.963: E/AndroidRuntime(1958): ... 11 more
You are writing your arrays using Parcel.writeStringArray but trying to read them using Parcel.readSerializable. Change your Vitamin constructor to match how you write writeToParcel. This should do it:
private Vitamin(Parcel in){
theName = in.readString();
theBenefits = in.createStringArray();
theFoods = in.createStringArray();
}
Alternatively, modify writeToParcel to write the string arrays as Serializable objects. Or you could put the arrays into a Bundle and write and then read the bundle.
Even better, switch to using ArrayList<String>, which I think provides better support for this.
Top of my head. One thing is missing when you try to get array.
Instead of doing
vitaminsList = getIntent().getParcelableArrayListExtra("VITAMINS");
try
vitaminsList = getIntent().getExtras.getParcelableArrayList("VITAMINS");
you should add more checks like...
Bundle b = getIntent().getExtras();
if(b!=null && b.containsKey("VITAMINS")){
vitaminsList = b.getParcelableArrayList("VITAMINS");
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With