mjd
mjd

Reputation: 119

Android Application: Runtime error when I try to get the Parcelable, which is passed as extra

I have a onItemClickListener which starts an Intent and puts a a Parcelable Object as extra.

This is the onItemClickListener Code:

@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//This is the value of the clicked Item
String clickedProjectName = (String) parent.getItemAtPosition(position);

//Create intent to start ProjectdetailActivity
Intent projectdetailIntent = new Intent(getActivity(),ProjectdetailActivity.class);

//get the Parcelable object
ProjectParcelable projectParcelable =  mProjectParcelableMap.get(clickedProjectName);

//put the Parcelable object as extra
projectdetailIntent.putExtra("ProjectParcelable", (ProjectParcelable)  projectParcelable);

//start activity
startActivity(projectdetailIntent);

The Membervariable mProjectParcelableMap is a HashMap of ProjectParcelables, where the Projectname (saved in clickedProjectName) is the Key.

This is the code in the onCreate method of the destination Intent:

//get received Intent
Intent receivedIntent = getActivity().getIntent();

//get ProjectParcelable from received Intent
ProjectParcelable projectParcelable = (ProjectParcelable)receivedIntent.getParcelableExtra("ProjectParcelable");
</pre>

The last command doesn't work. The App closes and throws the following errors:

11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime: FATAL EXCEPTION: main
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime: Process: com.example.application, PID: 19192
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime: java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.application/com.example.application.ProjectdetailActivity}: android.view.InflateException: Binary XML file line #2: Error inflating class fragment
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2379)
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2442)
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at android.app.ActivityThread.access$800(ActivityThread.java:156)
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1351)
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at android.os.Handler.dispatchMessage(Handler.java:102)
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at android.os.Looper.loop(Looper.java:211)
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at android.app.ActivityThread.main(ActivityThread.java:5373)
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at java.lang.reflect.Method.invoke(Native Method)
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at java.lang.reflect.Method.invoke(Method.java:372)
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1020)
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:815)
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:  Caused by: android.view.InflateException: Binary XML file line #2: Error inflating class fragment
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:763)
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at android.view.LayoutInflater.inflate(LayoutInflater.java:482)
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at android.view.LayoutInflater.inflate(LayoutInflater.java:414)
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at android.view.LayoutInflater.inflate(LayoutInflater.java:365)
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at android.support.v7.app.AppCompatDelegateImplV7.setContentView(AppCompatDelegateImplV7.java:257)
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:109)
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at com.example.application.ProjectdetailActivity.onCreate(ProjectdetailActivity.java:16)
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at android.app.Activity.performCreate(Activity.java:5990)
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2332)
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2442) 
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at android.app.ActivityThread.access$800(ActivityThread.java:156) 
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1351) 
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at android.os.Handler.dispatchMessage(Handler.java:102) 
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at android.os.Looper.loop(Looper.java:211) 
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at android.app.ActivityThread.main(ActivityThread.java:5373) 
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at java.lang.reflect.Method.invoke(Native Method) 
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at java.lang.reflect.Method.invoke(Method.java:372) 
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1020) 
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:815) 
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:  Caused by: java.lang.NullPointerException: Attempt to get length of null array
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at android.os.Parcel.readStringArray(Parcel.java:1031)
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at com.example.application.PersonParcelable.<init>(PersonParcelable.java:54)
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at com.example.application.PersonParcelable.<init>(PersonParcelable.java:9)
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at com.example.application.PersonParcelable$1.createFromParcel(PersonParcelable.java:96)
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at com.example.application.PersonParcelable$1.createFromParcel(PersonParcelable.java:90)
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at android.os.Parcel.readParcelable(Parcel.java:2283)
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at android.os.Parcel.readParcelableArray(Parcel.java:2369)
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at com.example.application.ProjectParcelable.<init>(ProjectParcelable.java:30)
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at com.example.application.ProjectParcelable.<init>(ProjectParcelable.java:9)
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at com.example.application.ProjectParcelable$1.createFromParcel(ProjectParcelable.java:71)
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at com.example.application.ProjectParcelable$1.createFromParcel(ProjectParcelable.java:63)
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at android.os.Parcel.readParcelable(Parcel.java:2283)
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at android.os.Parcel.readValue(Parcel.java:2183)
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at android.os.Parcel.readArrayMapInternal(Parcel.java:2516)
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at android.os.BaseBundle.unparcel(BaseBundle.java:221)
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at android.os.Bundle.getParcelable(Bundle.java:755)
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at android.content.Intent.getParcelableExtra(Intent.java:5089)
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at com.example.application.ProjectdetailFragment.onCreateView(ProjectdetailFragment.java:40)
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at android.support.v4.app.Fragment.performCreateView(Fragment.java:1965)
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1047)
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1237)
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at android.support.v4.app.FragmentManagerImpl.addFragment(FragmentManager.java:1339)
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at android.support.v4.app.FragmentManagerImpl.onCreateView(FragmentManager.java:2295)
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at android.support.v4.app.FragmentController.onCreateView(FragmentController.java:111)
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at android.support.v4.app.FragmentActivity.dispatchFragmentsOnCreateView(FragmentActivity.java:314)
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at android.support.v4.app.BaseFragmentActivityHoneycomb.onCreateView(BaseFragmentActivityHoneycomb.java:31)
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at android.support.v4.app.FragmentActivity.onCreateView(FragmentActivity.java:79)
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:     at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:733)
11-12 17:51:58.840 19192-19192/com.example.application E/AndroidRuntime:    ...

This is the code of the ProjectParcelable:

public class ProjectParcelable implements Parcelable {
   private String name;
   private PersonParcelable[] personParcelables;

   @Override
   public void writeToParcel(Parcel dest, int flags) {
       dest.writeString(name);
       dest.writeParcelableArray(personParcelables, flags);
   }

   private ProjectParcelable(Parcel in) {
       this.name = in.readString();
       in.readParcelableArray(PersonParcelable.class.getClassLoader());
   }

   public ProjectParcelable(String newName, PersonParcelable[] newPersonParcelables) {
       this.name = newName;
       this.personParcelables = newPersonParcelables;
   }

   //Getter
   public String getName() {
       return this.name;
   }

   public String[] getAllPersonNames() {
       String[] result = new String[personParcelables.length];
       for (int i = 0; i < personParcelables.length; i++) {
           result[i] = personParcelables[i].getName();
       }
       return result;
   }

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

   public static final Parcelable.Creator<ProjectParcelable> CREATOR = new Parcelable.Creator<ProjectParcelable>() {

       @Override
       public ProjectParcelable createFromParcel(Parcel source) {
           return new ProjectParcelable(source);
       }

       //We just need to copy this and change the type to match our class.

       @Override
       public ProjectParcelable[] newArray(int size) {
           return new ProjectParcelable[size];
       }
   };
}

This is the personParcelable:

public class PersonParcelable implements Parcelable {
   private String role;
   private String name;
   private String job;
   private String company;
   private String birthday;
   private String street;
   private String city;
   private String country;
   private String[] phones;
   private String[] mails;
   private String[] links;

   @Override
   public void writeToParcel(Parcel dest, int flags) {
       dest.writeString(role);
       dest.writeString(name);
       dest.writeString(job);
       dest.writeString(company);
       dest.writeString(birthday);
       dest.writeString(street);
       dest.writeString(city);
       dest.writeString(country);
       dest.writeStringArray(phones);
       dest.writeStringArray(mails);
       dest.writeStringArray(links);
   }

   private PersonParcelable(Parcel in) {
       this.role = in.readString();
       this.name = in.readString();
       this.job = in.readString();
       this.company = in.readString();
       this.birthday = in.readString();
       this.street = in.readString();
       this.city = in.readString();
       this.country = in.readString();
       in.readStringArray(phones);
       in.readStringArray(mails);
       in.readStringArray(links);
   }

   public PersonParcelable(String newRole, String newName, String newJob, String newCompany, String newBirthday, String newStreet, String newCity, String newCountry, String[] newPhones, String[] newMails, String[] newLinks) {
       this.role = newRole;
       this.name = newName;
       this.job = newJob;
       this.company = newCompany;
       this.birthday = newBirthday;
       this.street = newStreet;
       this.city = newCity;
       this.country = newCountry;
       this.phones = newPhones;
       this.mails = newMails;
       this.links = newLinks;
   }

   //Getter
   public String getName() {
       return this.name;
   }


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

   public static final Parcelable.Creator<PersonParcelable> CREATOR = new Parcelable.Creator<PersonParcelable>() {

       @Override
       public PersonParcelable createFromParcel(Parcel source) {
           return new PersonParcelable(source);
       }


       @Override
       public PersonParcelable[] newArray(int size) {
           return new PersonParcelable[size];
       }
   };
}    

Upvotes: 1

Views: 1114

Answers (1)

Kevin Coppock
Kevin Coppock

Reputation: 134704

So, two things:

The crash is caused here:

private PersonParcelable(Parcel in) {
    ...
    in.readStringArray(phones);
    in.readStringArray(mails);
    in.readStringArray(links);
}

Instead of using readStringArray, use createStringArray() and assign the result, like so:

private PersonParcelable(Parcel in) {
    ...
    this.phones = in.createStringArray();
    this.mails = in.createStringArray();
    this.links = in.createStringArray();
}

Using readStringArray() requires that you know the size of the array in advance, and preallocate the array, which is rarely what you actually want.

For the second issue, using readParcelableArray() is a pain due to type erasure. We have a custom utility method that does some awful generic array allocations and warning suppressions -- I would recommend using a List instead:

private List<PersonParcelable> personParcelables;

@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeString(name);
    dest.writeList(personParcelables);
}

private ProjectParcelable(Parcel in) {
    this.name = in.readString();
    this.personParcelables = in.readArrayList(PersonParcelable.class.getClassLoader());
}

Upvotes: 1

Related Questions