Parcel, ClassLoader and Reading Null values

穿精又带淫゛_ 提交于 2019-12-11 03:56:59

问题


I am trying to understand how to read null values from Parcel properly. Let's look my use case:

public class MyModel implements Parcelable {
    private Long id;
    private String name;

    public MyModel() {}

    public MyModel(Parcel in) {
        readFromParcel(in);
    }

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

    @Override public void writeToParcel(Parcel dest, int flags) {
        dest.writeValue(id);
        dest.writeValue(name);
    }

    public void readFromParcel(Parcel in) {
        id = (Long) in.readValue(Long.class.getClassLoader());
        name = (String) in.readValue(String.class.getClassLoader());
    }
}

For the sake of this question, let's take an example of field name which is of String type.

I understand I can use writeString instead of writeValue, but writeString will throw NullPointerException if name was null.

So now the real issue is, if name was null and i attempt to readValue and then casting null to String will throw an Exception.

What is the best approach to read null values from Parcel in that case? Do I need to check for null every time I attempt to read from Parcel? But that will be too much if you have a lot of fields in a model. Is there a difference between passing null or a ClassLoader when reading? Does a class loader returns an empty/default object if the value is null when reading Parcel?

The error I usually get is this, which happens when it is reading one of the Strings from Parcel:

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.company.MyActivity}: java.lang.RuntimeException: Parcel android.os.Parcel@42b82908: Unmarshalling unknown type code 7209045 at offset 1368


回答1:


What is the best approach to read null values from Parcel in that case?

You can use the string-specific methods:

  • Parcel.writeString(String)
  • Parcel.readString()

They work perfectly well with null values.


For example, assume you have a class with the following fields in it:

public class Test implements Parcelable {
    public final int id;
    private final String name;
    public final String description;
    ...

You create the Parcelable implementation like this (using Android Studio autoparcelable tool):

@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeInt(id);
    dest.writeString(null); // NOTE the null value here
    dest.writeString(description);
}

protected Test(Parcel in) {
    id = in.readInt();
    name = in.readString();
    description = in.readString();
}

Your Test.name value will be deserialised as null correctly, without requiring any casting to String.




回答2:


How about supply ClassLoader with MyModel.class. getClassLoader()?




回答3:


I think the best way to do this is to write the length of string name before name. If name is null, just write 0 as its length, and do not write name. When reading, if length is read and its value is zero, do not read name and just set name to null.



来源:https://stackoverflow.com/questions/26227095/parcel-classloader-and-reading-null-values

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!