Problem unmarshalling parcelables

后端 未结 10 1829
旧时难觅i
旧时难觅i 2020-11-27 15:45

I\'ve got a few classes that implement Parcelable and some of these classes contain each other as properties. I\'m marshalling the classes into a Parcel to pass them between

相关标签:
10条回答
  • 2020-11-27 16:19

    I got this exception because I was missing a constructor. The same must be done for all classes that implement Parcelable:

    // add new constructor
    @RequiresApi(Build.VERSION_CODES.N)
    private LocationType(Parcel dest, ClassLoader loader) {
        super(dest, loader);
        locid = dest.readInt();
        desc  = dest.readString();
        dir   = dest.readString();
        lat   = dest.readDouble();
        lng   = dest.readDouble();
    }
    
    public static final Creator<LayoverType> CREATOR = new ClassLoaderCreator<LayoverType>() {
    
        // add createFromParcel method with ClassLoader
        @Override
        public LayoverType createFromParcel(Parcel in, ClassLoader loader)
        {
            return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N ? new LayoverType(in, loader) : new LayoverType(in);
        }
    
        public LayoverType createFromParcel(Parcel in) {
            // call other createFromParcel method.    
            return createFromParcel(in, null);
        }
    
        public LayoverType[] newArray(int size) {
            return new LayoverType[size];
        }
    };
    
    0 讨论(0)
  • 2020-11-27 16:20

    I had the same problem with the following setup: some handler creates a Message and sends its over a Messenger to a remote service.

    the Message contains a Bundle where I put my Parcelable descendant:

    final Message msg = Message.obtain(null, 0);
    msg.getData().putParcelable("DOWNLOADFILEURLITEM", downloadFileURLItem);
    
    messenger.send(msg);
    

    I had the same exception when the remote service tried to unparcel. In my case, I had overseen that the remote service is indeed a separate os process. Therefore, I had to set the current classloader to be used by the unparcelling process on the service side:

    final Bundle bundle = msg.getData();
    bundle.setClassLoader(getClassLoader());
    
    DownloadFileURLItem urlItem = (DownloadFileURLItem)
    bundle.getParcelable("DOWNLOADFILEURLITEM");
    

    Bundle.setClassLoader sets the classloader which is used to load the appropriate Parcelable classes. In a remote service, you need to reset it to the current class loader.

    0 讨论(0)
  • 2020-11-27 16:20

    If you have an Object with a property of type of List objects you should pass the class loader when you read the property for example:

    public class Mall implements Parcelable {
    
        public List<Outstanding> getOutstanding() {
            return outstanding;
        }
    
        public void setOutstanding(List<Outstanding> outstanding) {
            this.outstanding = outstanding;
        }        
    
        protected Mall(Parcel in) {
            outstanding = new ArrayList<Outstanding>();
            //this is the key, pass the class loader
            in.readList(outstanding, Outstanding.class.getClassLoader());
        }
    
        @Override
        public int describeContents() {
            return 0;
        }
    
        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeList(outstanding);
        }
    
        public static final Parcelable.Creator<Mall> CREATOR = new Parcelable.Creator<Mall>() {
            public Mall createFromParcel(Parcel in) {
                return new Mall(in);
            }
    
            public Mall[] newArray(int size) {
                return new Mall[size];
            }
        };
    }
    

    Note: Is important that the class Outstanding implements the Parceable interface.

    0 讨论(0)
  • 2020-11-27 16:24

    I am not very familiar with Parcelable but if it's anything like Serialization each call to write an object that implements the interface will cause a recursive call to writeToParcel(). Therefore, if something along the call stack fails or writes a null value the class that initiated the call may not be constructed correctly.

    Try: Trace the writeToParcel() call stack through all the classes starting at the first call to writeToParcel() and verify that all the values are getting sent correctly.

    0 讨论(0)
提交回复
热议问题