web-dev-qa-db-ja.com

バンドルを介してオブジェクトを送信する方法

私の処理の大部分をバンドル経由で行うクラスへの参照を渡す必要があります。

問題は、インテントやコンテキストとは関係がなく、大量の非プリミティブオブジェクトがあることです。クラスをparcelable/serializableにパッケージ化し、startActivityForResultに渡すにはどうすればよいですか?

114
ahodder

進むべき道を見つけるには、CommonsWareの「なぜ」という重要な質問だけでなく、「何に」という質問にも答える必要があります。あなたはそれを渡しますか?.

現実には、バンドルを通過できるのはプレーンデータだけです。他のすべては、そのデータが意味するまたは指すものの解釈に基づいています。オブジェクトを文字通り渡すことはできませんが、できることは次の3つのうちの1つです。

1)オブジェクトを構成データに分解し、反対側に同じ種類のオブジェクトの知識がある場合、シリアル化されたデータからクローンを組み立てることができます。これが、ほとんどの一般的なタイプがバンドルを通過する方法です。

2)不透明なハンドルを渡すことができます。同じコンテキスト内でそれを渡す場合(なぜわざわざ尋ねるかもしれませんが)それがハンドルになるので、呼び出したり、逆参照したりできます。ただし、Binderを介して別のコンテキストに渡すと、リテラル値は任意の数値になります(実際、これらの任意の数値は起動時から順番にカウントされます)。元のコンテキストに戻すまでBinderを元のハンドルに戻して、再び便利にするまで、何もできません。

3)ファイル記述子または特定のOS /プラットフォームオブジェクトへの参照などのマジックハン​​ドルを渡すことができます。正しいフラグを設定すると、バインダーは受信者の同じリソースを指すクローンを作成します。もう一方の端。ただし、これはごく一部の種類のオブジェクトでのみ機能します。

ほとんどの場合、相手側がクラスを追跡して後で返すことができるようにクラスを渡すか、シリアル化された構成データからクローンを作成できるコンテキストに渡します...またはうまくいかないことをしようとしているので、アプローチ全体を再考する必要があります。

55
Chris Stratton

Gsonを使用してオブジェクトをJSONObjectに変換し、バンドルで渡すこともできます。私にとってこれが最もエレガントな方法でした。パフォーマンスへの影響をテストしていません。

初期活動中

Intent activity = new Intent(MyActivity.this,NextActivity.class);
activity.putExtra("myObject", new Gson().toJson(myobject));
startActivity(activity);

次のアクティビティで

String jsonMyObject;
Bundle extras = getIntent().getExtras();
if (extras != null) {
   jsonMyObject = extras.getString("myObject");
}
MyObject myObject = new Gson().fromJson(jsonMyObject, MyObject.class);
151
Laranjeiro

Parcelableインターフェースは、オブジェクトをインテントで渡すための良い方法です。

カスタムオブジェクトをParcelableにするにはどうすればよいですか? は、使用方法に関するかなり良い答えですParcelable

公式の google docs にも例が含まれています

19
chris

グローバル application 状態を使用できます。

更新:

これをカスタマイズして、AndroidManifest.xmlに追加します。

<application Android:label="@string/app_name" Android:debuggable="true" Android:name=".CustomApplication"

次に、プロジェクトに次のようなクラスを作成します。

package com.example;

import Android.app.Application;

public class CustomApplication extends Application {
    public int someVariable = -1;
}

そして、「 アクティビティまたはサービスからgetApplication()を介してアクセスできる 」なので、次のように使用します。

CustomApplication application = (CustomApplication)getApplication();
application.someVariable = 123; 

それが役に立てば幸いです。

14
Neil

オブジェクトを Serializable にして、バンドルの getSerializable および putSerializable メソッドを使用することもできます。

11
dhaag23

可能な解決策:

Bundle bundle = new Bundle();
bundle.putSerializable("key", new CustomObject());

クラスCustomObject:

class CustomObject implements Serializable{
 private SubCustomObject1 sc1;
 private SubCustomObject2 sc2;
}

サブカスタムオブジェクト:

class SubCustomObject1 implements Serializable{ }

class SubCustomObject2  implements Serializable{ }
10
PraKhar

バンドルを介してオブジェクトを送信するもう1つの方法は、bundle.putByteArrayを使用することです
サンプルコード

public class DataBean implements Serializable {
private Date currentTime;

public setDate() {
    currentTime = Calendar.getInstance().getTime();
 }

public Date getCurrentTime() {
    return currentTime;
 }
}

dataBeanのオブジェクトをバンドルに配置します。

class FirstClass{
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Your code...

//When you want to start new Activity...
Intent dataIntent =new Intent(FirstClass.this, SecondClass.class);
            Bundle dataBundle=new Bundle();
            DataBean dataObj=new DataBean();
            dataObj.setDate();
            try {
                dataBundle.putByteArray("Obj_byte_array", object2Bytes(dataObj));

            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();

            }

            dataIntent.putExtras(dataBundle);

            startActivity(dataIntent);
}

オブジェクトをバイト配列に変換する

/**
 * Converting objects to byte arrays
 */
static public byte[] object2Bytes( Object o ) throws IOException {
      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      ObjectOutputStream oos = new ObjectOutputStream( baos );
      oos.writeObject( o );
      return baos.toByteArray();
    }

バンドルからオブジェクトを取得する:

class SecondClass{
DataBean dataBean;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Your code...

//Get Info from Bundle...
    Bundle infoBundle=getIntent().getExtras();
    try {
        dataBean = (DataBean)bytes2Object(infoBundle.getByteArray("Obj_byte_array"));
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

バイト配列からオブジェクトを取得する方法:

/**
 * Converting byte arrays to objects
 */
static public Object bytes2Object( byte raw[] )
        throws IOException, ClassNotFoundException {
      ByteArrayInputStream bais = new ByteArrayInputStream( raw );
      ObjectInputStream ois = new ObjectInputStream( bais );
      Object o = ois.readObject();
      return o;
    }

これが他の仲間に役立つことを願っています。

7
Rupesh Yadav

1.非常に直接的で使いやすい例で、渡されるオブジェクトにSerializableを実装させます。

class Object implements Serializable{
    String firstName;
   String lastName;
}

2.バンドル内のオブジェクトを渡す

Bundle bundle = new Bundle();
Object Object = new Object();
bundle.putSerializable("object", object);
  1. バンドルから渡されたオブジェクトをSerializableとして取得し、Objectにキャストします。

    オブジェクトobject =(Object)getArguments()。getSerializable( "object");

1
king_T

Dateオブジェクトを渡す方法を探していたときに、この質問に出会いました。私の場合、回答の中で提案されたように、Bundle.putSerializable()を使用しましたが、元の記事で説明されているDataManagerのように複雑なものには機能しません。

前述のDataManagerをアプリケーションに配置したり、Singletonにしたりするのと非常によく似た結果をもたらす私の提案は、Dependency Injectionを使用してDataManagerをSingletonスコープにバインドし、必要な場所にDataManagerを挿入することです。テスト容易性が向上するだけでなく、「クラスとアクティビティ間で依存関係を渡す」ボイラープレートのすべてのコードがなくても、よりクリーンなコードが得られます。 (Robo)Guice は非常に使いやすく、新しい Dagger フレームワークも有望に見えます。

0
britzl

バンドルを使用してオブジェクトを渡す別の簡単な方法:

  • クラスオブジェクトで、キーを使用して静的リストまたは別のデータ構造を作成します。
  • オブジェクトを作成するときに、キーを使用してリスト/データ構造に入れます(オブジェクトが作成されたときの長いタイムスタンプ)
  • リストからオブジェクトを取得するメソッドgetObject(long key)を作成します
  • バンドルでキーを渡すので、後でコードの別のポイントからオブジェクトを取得できます
0
shaolin