web-dev-qa-db-ja.com

Parcelableインターフェイスを使用するときにnull値をシリアル化する方法

私のコード例に関して、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());
    }

}

ありがとう!

60
igor.beslic

Parcel.writeValueを使用して、汎用オブジェクトをnull値でマーシャリングできます。

102
artch

ParcelableフィールドとIntegerフィールドも持つBooleanクラスを使用していますが、これらのフィールドはnullでもかまいません。

一般的なParcel.writeValueメソッドの使用に問題がありました。特にParcel.readValueを介して読み戻そうとしたときです。パーセルされたオブジェクトのタイプを判別できないと言ったランタイム例外を受け取り続けました。

最終的に、IntegerBooleanの両方がSerializableインターフェイスを実装しているため、型キャストでParcel.writeSerializableParcel.readSerializableを使用することで問題を解決できました。読み取りおよび書き込みメソッドはnull値を処理します。

19
Justin Hong

これは、文字列を安全に記述するために思いついた解決策です。

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;
}
14
Felipe Lima

私が見たほとんどのシリアル化コードは、いずれかのフラグを使用して、値の有無を示します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にならないことを保証でき、特別なコードを追加する必要はありませんシリアル化/逆シリアル化メソッドでそれを使用して)。

13
David Wasser