私のコード例に関して、1つのLocableの変数がnullの場合はどうすればいいですか?たとえば、l.getZoom()がnullを返す場合、NullPointerExceptionが発生します。
@Override
public void writeToParcel(Parcel parcel, int arg1) {
parcel.writeInt(count);
for(Locable l:locableArr){
parcel.writeInt(l.getOriginId());
parcel.writeInt(l.getLocableType());
parcel.writeInt(l.getZoom());
parcel.writeDouble(l.getLatituda());
parcel.writeDouble(l.getLongituda());
parcel.writeString(l.getTitle());
parcel.writeString(l.getSnipet());
}
}
ありがとう!
Parcel.writeValue
を使用して、汎用オブジェクトをnull値でマーシャリングできます。
Parcelable
フィールドとInteger
フィールドも持つBoolean
クラスを使用していますが、これらのフィールドはnullでもかまいません。
一般的なParcel.writeValue
メソッドの使用に問題がありました。特にParcel.readValue
を介して読み戻そうとしたときです。パーセルされたオブジェクトのタイプを判別できないと言ったランタイム例外を受け取り続けました。
最終的に、Integer
とBoolean
の両方がSerializableインターフェイスを実装しているため、型キャストでParcel.writeSerializable
とParcel.readSerializable
を使用することで問題を解決できました。読み取りおよび書き込みメソッドはnull
値を処理します。
これは、文字列を安全に記述するために思いついた解決策です。
private void writeStringToParcel(Parcel p, String s) {
p.writeByte((byte)(s != null ? 1 : 0));
p.writeString(s);
}
private String readStringFromParcel(Parcel p) {
boolean isPresent = p.readByte() == 1;
return isPresent ? p.readString() : null;
}
私が見たほとんどのシリアル化コードは、いずれかのフラグを使用して、値の有無を示しますORは、値の前にcountフィールドがあります(配列を書き込むときなど)値がまったく存在しない場合は、ゼロに設定します。
Androidコアクラスのソースコードを調べると、次のようなコードが明らかになります(メッセージクラスから):
if (obj != null) {
try {
Parcelable p = (Parcelable)obj;
dest.writeInt(1);
dest.writeParcelable(p, flags);
} catch (ClassCastException e) {
throw new RuntimeException(
"Can't marshal non-Parcelable objects across processes.");
}
} else {
dest.writeInt(0);
}
またはこれ(Intentクラスから):
if (mCategories != null) {
out.writeInt(mCategories.size());
for (String category : mCategories) {
out.writeString(category);
}
} else {
out.writeInt(0);
}
私の提案:コードで、「zoom == null」と「zoom == 0」の間に機能的な違いがない場合、ズームをプリミティブとして宣言します(int
の代わりにInteger
) ORコンストラクターでゼロに初期化し、nullに設定しないようにします(nullにならないことを保証でき、特別なコードを追加する必要はありませんシリアル化/逆シリアル化メソッドでそれを使用して)。