Parcelableインターフェースを実装するときにブール値を読み書きする方法は?


404

ArrayList Parcelableアクティビティにカスタムオブジェクトのリストを渡すためにを作成しようとしています。myObjectList拡張ArrayList<myObject>して実装するクラスを書き始めますParcelable

の一部の属性はメソッドですMyObjectbooleanParcelありませんread/writeBoolean

これを処理する最良の方法は何ですか?


3
アクティビティ間でオブジェクトを渡すことについて行ったすべての読み取りは、シリアライズ可能ではなくパーセル可能の使用を先取りしています。
2011年

10
@MisterSquonkインタラクティビティSerializable通信にはインターフェースを使用しないでください。遅いです。
Octavian A. Damiean

1
@grunk:わかりました。まあまあですが、Intent.putExtra(String name、Serializable value)がドキュメントで非推奨とマークされるまで、私にとってそれが使いやすくなれば、引き続き使用できます。ちょっとした考え。
Squonk

3
@オクタビアン:しかし、それはケースごとの研究に依存し、相対的です。
Squonk

2
私の意見では、アンドロイドの建築家チームは怠惰です!!! whereis boolean !!!!!!!!
マテウス2013年

回答:


942

これが私のやり方です...

writeToParcel:

dest.writeByte((byte) (myBoolean ? 1 : 0));     //if myBoolean == true, byte == 1

readFromParcel:

myBoolean = in.readByte() != 0;     //myBoolean == true if byte != 0

38
intでバイトを使用する理由はありません。キャストのため、バイトはより冗長です。dest.writeInt(myBoolean?1:0);
ミゲル2015年

@SiPlusコメントになぜ多くの賛成票が与えられたのですか?1も0もまったくロードされません。まったく違いはありません。そして、いつJavaが弱く型付けされた言語になったのですか?
誰も

13
バイトを書き込み@sotrhちょうどint型を書き込みます/** * Write a byte value into the parcel at the current dataPosition(), * growing dataCapacity() if needed. */ public final void writeByte(byte val) { writeInt(val); }
ダラス

3
@ダラスはドキュメントからですか?もしそうなら、私のコメントは無視してください。apiがと言う関数を持っているのは不誠実なようですwriteByteが、実際にはintを書き込みます。
sotrh

1
@sotrhは、ソースコードからのコピーと貼り付けです。android.os.Parcelソースを開いて、自分の目で確かめてください。
Yaroslav Mytkalyk 16年

66

また、writeValueメソッドを使用することもできます。私の意見では、それは最も簡単な解決策です。

dst.writeValue( myBool );

その後、次のようにキャストするだけで簡単に取得できますBoolean

boolean myBool = (Boolean) source.readValue( null );

内部的には、Androidフレームワークは整数として処理します。

writeInt( (Boolean) v ? 1 : 0 );

「ボンネットの下」の部分を示すAndroidソース(l。1219)。(メソッド呼び出しとスイッチのため)少し効率が落ちますが、このメソッドは少しわかりやすくなります。
2014

6
ここに書かれたコードはコンパイルされません。readValueにはクラスローダーが必要ですが、ブール値には必要ありません。「boolean myBool =(Boolean)source.readValue(null);」と表示されます。何をしているのかわからず、この回答に対する編集を拒否したレビューア:@hemang、ジープ、DavidRR。
ミゲル2015年

1
@miguelそれは真実です、それを修正しました:)
Taig

15

あなたはこのように宣言します

 private boolean isSelectionRight;

書く

 out.writeInt(isSelectionRight ? 1 : 0);

読んだ

isSelectionRight  = (in.readInt() == 0) ? false : true;

ブール型は、Parcelがサポートするものに変換する必要があるため、intに変換できます。


これによりエラーが発生し、互換性のない型が必要なブール値がintに見つかりましたか?
ポール・

12

AndroidStudio(2.3 atmを使用)、クラスにParcelableを実装した後、クラス名の上にマウスポインターを置くだけで、Parcelable実装を追加するように求められます。

ここに画像の説明を入力してください

4つのフィールドから、以下を生成します。

public class YourClass implements Parcelable{

String someString;
int someInt;
boolean someBoolean;
List<String> someList;

protected YourClass(Parcel in) {
    someString = in.readString();
    someInt = in.readInt();
    someBoolean = in.readByte() != 0;
    someList = in.createStringArrayList();
}

@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeString(someString);
    dest.writeInt(someInt);
    dest.writeByte((byte) (someBoolean ? 1 : 0));
    dest.writeStringList(someList);
}

...

これは便利です:)
Dino Tw

8

私は通常それらを配列に入れて呼び出しwriteBooleanArrayreadBooleanArray

パックする必要がある単一のブール値の場合は、次のようにすることができます。

parcel.writeBooleanArray(new boolean[] {myBool});

いくつかのブール値を分割する必要があるときに問題に直面したことがありますか?助けてくれませんか?stackoverflow.com/questions/13463727/…。ありがとう。
ロジャーエイリアン

8
out.writeInt(mBool ? 1 : 0); //Write
this.mBool =in.readInt()==1; //Read

5

Android Studioを使用している場合、Parcelableを実装する最も簡単な方法を提案しました。

単純に行くファイル- >設定- > Plugins->ブラウズリポジトリとparcelable .Seeの画像を検索

ここに画像の説明を入力してください Parcelableが自動的に作成されます。

そして、これを行うためのwebisteもあります。http://www.parcelabler.com/


4

null許容サポートを備えたKotlinの短くてシンプルな実装:

Parcelにメソッドを追加する

fun Parcel.writeBoolean(flag: Boolean?) {
    when(flag) {
        true -> writeInt(1)
        false -> writeInt(0)
        else -> writeInt(-1)
    }
}

fun Parcel.readBoolean(): Boolean? {
    return when(readInt()) {
        1 -> true
        0 -> false
        else -> null
    }
}

そしてそれを使う:

parcel.writeBoolean(isUserActive)

parcel.readBoolean()        // For true, false, null
parcel.readBoolean()!!      // For only true and false

@AliKaziでは、Javaの1行のステートメントで、オプションの型をサポートすることはできません。3つの状態を維持する必要があります。nullのことは忘れていると思います。
Pavel Shorokhov

@ comm1x、IDEはこのソリューションを好みません。`スーパークラスのコンストラクタが呼び出される前に「readBoolean」にアクセスできません。
Adam Hurwitz

@ comm1x問題を解決しました。動作させるためには、追加されたメソッドはコンパニオンオブジェクト
Adam Hurwitz

3

マスキングとシフトを使用してブール値をバイトにパックできます。それが最も効率的な方法であり、おそらく彼らがあなたに期待することでしょう。


+1。True、値をバイトに保存する方が効率的です。あなたのアイデアを表すために私の質問を編集していただけませんか。
Octavian A. Damiean

できますが、あなたが書いたものは、私が意図したものではありません。機能しますが、最も効率的ではありません。マスクとブール代数を使用して、1つのバイトに8つのブール値をパックできます
fleetway76

ほとんどの場合、私はあなたに同意しますが、ブールが機能する3つの状態が必要な場合があります。オプションのはい/いいえの質問など。ブール値が明示的に指定されているかどうかを知るにはnullが必要です。
Chad Gorshing

ParcelのwriteByte()メソッドが直接呼び出すため、バイトオーバーintを使用する理由はありませんwriteInt()
Yaroslav Mytkalyk

3

ここで本当の質問を特定するのは困難です。Parcelableインターフェイスを実装するときにブール値を処理する方法だと思います。

MyObjectの一部の属性はブール値ですが、Parcelにはメソッドread / writeBooleanがありません。

値を文字列またはバイトとして保存する必要があります。文字列を取得する場合は、String呼び出さvalueOf()れたクラスの静的メソッドを使用してブール値を解析する必要があります。これを1バイトに保存するほど効果的ではありません。

String.valueOf(theBoolean);

あなたがバイトに行くなら、あなたはあなた自身で変換ロジックを実装しなければならないでしょう。

byte convBool = -1;
if (theBoolean) {
    convBool = 1;
} else {
    convBool = 0;
}

Parcelオブジェクトを非整列化するときは、元の型への変換に注意する必要があります。


Stringを使用する理由はまったくありません。ParcelのwriteByte()メソッドがを直接呼び出すので、int over byteを使用する理由はありませんwriteInt()。変換ロジックが冗長すぎます。ただ、やるwriteInt(boolean ? 1 : 0)boolean = readInt() != 0
ヤロスラフMytkalyk

1

この質問は、自分でやりたい場合は、すでに他の人から完全に回答されています。

低レベルのパーセリングコードの大部分をカプセル化または非表示にする場合は、パーセルの処理を簡略化するために、少し前に書いたコードの一部を使用することを検討してください。

小包への書き込みは次のように簡単です:

parcelValues(dest, name, maxSpeed, weight, wheels, color, isDriving);

たとえば、colorは列挙型で、isDrivingはブール値です。

小包からの読み取りもそれほど難しくありません。

color = (CarColor)unparcelValue(CarColor.class.getClassLoader());
isDriving = (Boolean)unparcelValue();

プロジェクトに追加した「ParceldroidExample」を見てください。

最後に、CREATORイニシャライザを短く保ちます。

public static final Parcelable.Creator<Car> CREATOR =
    Parceldroid.getCreatorForClass(Car.class);

をありがとう.class.getClassLoader()
CoolMind

0

Android(AOSP)ソースには多くの例があります。たとえば、PackageInfoクラスにはブールメンバーがrequiredForAllUsersあり、次のようにシリアル化されます。

public void writeToParcel(Parcel dest, int parcelableFlags) {
    ...
    dest.writeInt(requiredForAllUsers ? 1 : 0);
    ...
}

private PackageInfo(Parcel source) {
    ...
    requiredForAllUsers = source.readInt() != 0;
    ...
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.