问题
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