あるActivity
から自分の customer クラスのオブジェクトを送信し、それを別のActivity
に表示しようとしています。
顧客クラスのコード:
public class Customer {
private String firstName, lastName, Address;
int Age;
public Customer(String fname, String lname, int age, String address) {
firstName = fname;
lastName = lname;
Age = age;
Address = address;
}
public String printValues() {
String data = null;
data = "First Name :" + firstName + " Last Name :" + lastName
+ " Age : " + Age + " Address : " + Address;
return data;
}
}
オブジェクトをある[_ VARIABLE] _から別のActivity
に送信してから、他のActivity
にデータを表示したいのです。
どうすればそれを達成できますか?
1つの選択肢は、カスタムクラスにSerializable
インターフェースを実装させ、putExtra(Serializable..)
メソッドのIntent#putExtra()
バリアントを使ってインテントエクストラでオブジェクトインスタンスを渡すことができます。
擬似コード :
//To pass:
intent.putExtra("MyClass", obj);
// To retrieve object in second Activity
getIntent().getSerializableExtra("MyClass");
注:メインのカスタムクラスのネストした各クラスに、シリアル化の例外を回避するためのSerializableインタフェースが実装されていることを確認してください。例えば:
class MainClass implements Serializable {
public MainClass() {}
public static class ChildClass implements Serializable {
public ChildClass() {}
}
}
クラスをSerializableで実装します。これがあなたのエンティティクラスだとしましょう:
import Java.io.Serializable;
@SuppressWarnings("serial") //With this annotation we are going to hide compiler warnings
public class Deneme implements Serializable {
public Deneme(double id, String name) {
this.id = id;
this.name = name;
}
public double getId() {
return id;
}
public void setId(double id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
private double id;
private String name;
}
dene
というオブジェクトをXアクティビティからYアクティビティに送信しています。 Xのどこかにあります。
Deneme dene = new Deneme(4,"Mustafa");
Intent i = new Intent(this, Y.class);
i.putExtra("sampleObject", dene);
startActivity(i);
Yアクティビティでは、オブジェクトを取得しています。
Intent i = getIntent();
Deneme dene = (Deneme)i.getSerializableExtra("sampleObject");
それでおしまい。
あなたはこの site を使ってあなたのクラスのためのParcelableコードを生成することができます。
活動を呼びながら
Intent intent = new Intent(fromClass.this,toClass.class).putExtra("myCustomerObj",customerObj);
ToClass.Javaでアクティビティを受け取ります。
Customer customerObjInToClass = getIntent().getExtras().getParcelable("myCustomerObj");
顧客クラスが解析可能を実装していることを確認してください
public class Customer implements Parcelable {
private String firstName, lastName, address;
int age;
/* all your getter and setter methods */
public Customer(Parcel in ) {
readFromParcel( in );
}
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
public LeadData createFromParcel(Parcel in ) {
return new Customer( in );
}
public Customer[] newArray(int size) {
return new Customer[size];
}
};
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(firstName);
dest.writeString(lastName);
dest.writeString(address);
dest.writeInt(age);
}
private void readFromParcel(Parcel in ) {
firstName = in .readString();
lastName = in .readString();
address = in .readString();
age = in .readInt();
}
私の経験では3つの主な解決策があり、それぞれに欠点と利点があります。
Parcelableを実装する
直列化可能オブジェクトの実装
ある種の軽量イベントバスライブラリを使用する(例えば、GreenrobotのEventBusやSquareのOtto)
Parcelable - 高速でAndroidの標準ですが、定型コードをたくさん持っているため、意図を超えて値を引き出すときには参照用にハードコードされた文字列が必要です。
直列化可能 - ゼロ定型句に近いが、これは最も遅いアプローチであり、値を意図的に引き出すときにハードコーディングされた文字列も必要です(強く型付けされていない)。
イベントバス - ゼロボイラープレート、最速のアプローチ、ハードコードされた文字列は不要ですが、追加の依存関係が必要です(通常は軽量、40 KB以下)。
効率ベンチマークを含め、これら3つのアプローチについて非常に詳細な比較を掲載しました。
gson を使用してオブジェクトをJSONに変換し、インテントに渡します。新しいActivityでJSONをオブジェクトに変換します。
あなたのbuild.gradle
で、これをあなたの依存関係に追加してください
implementation 'com.google.code.gson:gson:2.8.4'
アクティビティで、オブジェクトをjson-stringに変換します。
Gson gson = new Gson();
String myJson = gson.toJson(vp);
intent.putExtra("myjson", myjson);
受信アクティビティで、json文字列を元のオブジェクトに変換します。
Gson gson = new Gson();
YourObject ob = gson.fromJson(getIntent().getStringExtra("myjson"), YourObject.class);
Kotlin の場合はまったく同じです
データを渡す
val gson = Gson()
val intent = Intent(this, YourActivity::class.Java)
intent.putExtra("identifier", gson.toJson(your_object))
startActivity(intent)
データを受け取る
val gson = Gson()
val yourObject = gson.fromJson<YourObject>(intent.getStringExtra("identifier"), YourObject::class.Java)
オブジェクトのデータを一時的な文字列や整数に書き込み、それらをアクティビティに渡すこともできます。もちろんそのようにして、データは転送されますが、オブジェクト自体は転送されません。
しかし、それらを表示したいだけで、他のメソッドやそのようなものでオブジェクトを使用しないのであれば、それで十分です。あるオブジェクトのデータを別のアクティビティに表示するのと同じ方法で行いました。
String fName_temp = yourObject.getFname();
String lName_temp = yourObject.getLname();
String age_temp = yourObject.getAge();
String address_temp = yourObject.getAddress();
Intent i = new Intent(this, ToClass.class);
i.putExtra("fname", fName_temp);
i.putExtra("lname", lName_temp);
i.putExtra("age", age_temp);
i.putExtra("address", address_temp);
startActivity(i);
あなたはそれらを一時的なivarsの代わりに直接渡すこともできます、しかしこの方法は私の意見ではより明確です。さらに、Temp ivarsをnullに設定して、GarbageCollectorによってクリーンになるようにすることもできます。
がんばろう!
注意事項:独自のprintメソッドを書く代わりにtoString()をオーバーライドしてください。
下記のコメントで述べたように、これはあなたがあなたのデータを他の活動に戻す方法です。
String fName = getIntent().getExtras().getInt("fname");
私はシンプルでエレガントな方法を見つけました:
最初のアクティビティのコード:
final Object objSent = new Object();
final Bundle bundle = new Bundle();
bundle.putBinder("object_value", new ObjectWrapperForBinder(objSent));
startActivity(new Intent(this, SecondActivity.class).putExtras(bundle));
Log.d(TAG, "original object=" + objSent);
2番目のアクティビティのコード:
final Object objReceived = ((ObjectWrapperForBinder)getIntent().getExtras().getBinder("object_value")).getData();
Log.d(TAG, "received object=" + objReceived);
objSent
とobjReceived
は同じhashCode
を持っているので、それらは同一です。
しかし、どうしてこのようにしてJavaオブジェクトを渡すことができるのでしょうか。
実際には、AndroidバインダーはJavaオブジェクトのグローバルJNI参照を作成し、このJavaオブジェクトの参照がない場合はこのグローバルJNI参照を解放します。バインダーは、このグローバルJNI参照をBinderオブジェクトに保存します。
*注意:このメソッドは、2つのアクティビティが同じプロセスで実行されない限り機能します。それ以外の場合は、(ObjectWrapperForBinder)getIntent()。getExtras()。getBinder( "object_value")*
クラスObjectWrapperForBinderの定義
public class ObjectWrapperForBinder extends Binder {
private final Object mData;
public ObjectWrapperForBinder(Object data) {
mData = data;
}
public Object getData() {
return mData;
}
}
しかし、レシーバがJavaオブジェクトを復元できなかった場合(たとえば、Javaオブジェクトを復元する前に何らかの例外が発生した場合、またはレシーバアクティビティがまったく存在しない場合)、方法2には多少深刻な問題があります。 Androidバインダーがこの例外を処理するため、孤立またはメモリリーク、方法1ではこの問題は発生しません。
Javaオブジェクトをリモートで呼び出すために、Javaオブジェクトを記述するためのデータコントラクト/インタフェースを作成します。補助ファイルを使用します。
IDataContract.aidl
package com.example.objectwrapper;
interface IDataContract {
int func1(String arg1);
int func2(String arg1);
}
最初の活動のコード
final IDataContract objSent = new IDataContract.Stub() {
@Override
public int func2(String arg1) throws RemoteException {
// TODO Auto-generated method stub
Log.d(TAG, "func2:: arg1=" + arg1);
return 102;
}
@Override
public int func1(String arg1) throws RemoteException {
// TODO Auto-generated method stub
Log.d(TAG, "func1:: arg1=" + arg1);
return 101;
}
};
final Bundle bundle = new Bundle();
bundle.putBinder("object_value", objSent.asBinder());
startActivity(new Intent(this, SecondActivity.class).putExtras(bundle));
Log.d(TAG, "original object=" + objSent);
2番目のアクティビティのコード:
AndroidManifest.xmlのAndroid:process属性を空でないプロセス名に変更して、2番目のアクティビティが別のプロセスで実行されるようにします
final IDataContract objReceived = IDataContract.Stub.asInterface(getIntent().getExtras().getBinder("object_value"));
try {
Log.d(TAG, "received object=" + objReceived + ", func1()=" + objReceived.func1("test1") + ", func2()=" + objReceived.func2("test2"));
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
このようにして、2つのアクティビティが異なるプロセスで実行されていても、それらの間にインタフェースを渡し、インタフェースメソッドをリモートで呼び出すことができます。
方法3は、私たちが援助インタフェースを実装しなければならないので、十分に単純ではないようです。単純なタスクを実行したいだけで、メソッドの戻り値が不要な場合は、Android.os.Messengerを使用できます。
最初の活動(送信者)のコード:
public class MainActivity extends Activity {
private static final String TAG = "MainActivity";
public static final int MSG_OP1 = 1;
public static final int MSG_OP2 = 2;
public static final String EXTRA_MESSENGER = "messenger";
private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
Log.e(TAG, "handleMessage:: msg=" + msg);
switch (msg.what) {
case MSG_OP1:
break;
case MSG_OP2:
break;
default:
break;
}
super.handleMessage(msg);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startActivity(new Intent(this, SecondActivity.class).putExtra(EXTRA_MESSENGER, new Messenger(mHandler)));
}
}
2番目の活動(受信者)のコード
public class SecondActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
final Messenger messenger = getIntent().getParcelableExtra(MainActivity.EXTRA_MESSENGER);
try {
messenger.send(Message.obtain(null, MainActivity.MSG_OP1, 101, 1001, "10001"));
messenger.send(Message.obtain(null, MainActivity.MSG_OP2, 102, 1002, "10002"));
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Messenger.sendはすべて、Handler内で非同期かつ順次に実行されます。
実際には、Android.os.Messengerは、あなたがAndroidのソースコードを持っていれば、IMessenger.aidlという名前のファイルを見つけることができます。
package Android.os;
import Android.os.Message;
/** @hide */
oneway interface IMessenger {
void send(in Message msg);
}
一時オブジェクトを保持するシングルトンヘルパークラスを作りました。
public class IntentHelper {
private static IntentHelper _instance;
private Hashtable<String, Object> _hash;
private IntentHelper() {
_hash = new Hashtable<String, Object>();
}
private static IntentHelper getInstance() {
if(_instance==null) {
_instance = new IntentHelper();
}
return _instance;
}
public static void addObjectForKey(Object object, String key) {
getInstance()._hash.put(key, object);
}
public static Object getObjectForKey(String key) {
IntentHelper helper = getInstance();
Object data = helper._hash.get(key);
helper._hash.remove(key);
helper = null;
return data;
}
}
オブジェクトをIntent内に配置する代わりに、IntentHelperを使用してください。
IntentHelper.addObjectForKey(obj, "key");
新しいActivityの中に、オブジェクトを取得することができます。
Object obj = (Object) IntentHelper.getObjectForKey("key");
いったんロードされると、不要な参照を避けるためにオブジェクトは削除されることに注意してください。
他のクラスやアクティビティの変数やオブジェクトにアクセスする方法はいくつかあります。
A.データベース
B.共有設定.
C.オブジェクトの直列化.
D.共通データを保持できるクラスは、Common Utilitiesと名付けることができます。あなた次第です。
E.インテントとParcelable Interfaceを通してデータを渡す。
プロジェクトのニーズによって異なります。
A. データベース
SQLite はAndroidに組み込まれているオープンソースのデータベースです。 SQLiteは、SQL構文、トランザクション、プリペアドステートメントなどの標準リレーショナルデータベース機能をサポートします。
B. 共有設定
ユーザ名を保存したいとしましょう。そのため、 key username、 value valueの2つになります。
保存方法
// Create object of SharedPreferences.
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
//Now get Editor
SharedPreferences.Editor editor = sharedPref.edit();
//Put your value
editor.putString("userName", "stackoverlow");
//Commits your edits
editor.commit();
putString()、putBoolean()、putInt()、putFloat()、およびputLong()を使用すると、必要なdtatypeを保存できます。
取得方法
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
String userName = sharedPref.getString("userName", "Not Available");
http://developer.Android.com/reference/Android/content/SharedPreferences.html
C. オブジェクト直列化
オブジェクトの状態を保存してネットワーク経由で送信したい場合や、目的にも使用できる場合は、オブジェクトのセル化が使用されます。
Java Beansを使用してそれを彼のフィールドの1つとして格納し、そのためにgetterとsetterを使用します。
JavaBeans は、プロパティを持つJavaクラスです。プロパティをプライベートインスタンス変数と見なします。これらは非公開なので、クラスの外部からアクセスできる唯一の方法は、クラス内のメソッドを使用することです。プロパティの値を変更するメソッドは設定メソッドと呼ばれ、プロパティの値を取得するメソッドは取得メソッドと呼ばれます。
public class VariableStorage implements Serializable {
private String inString;
public String getInString() {
return inString;
}
public void setInString(String inString) {
this.inString = inString;
}
}
を使用してメールメソッドに変数を設定します。
VariableStorage variableStorage = new VariableStorage();
variableStorage.setInString(inString);
次に、オブジェクト直列化を使用してこのオブジェクトを直列化し、他のクラスでこのオブジェクトを直列化復元します。
直列化では、オブジェクトは、オブジェクトのデータ、およびオブジェクトの種類とオブジェクトに格納されているデータの種類に関する情報を含む一連のバイトとして表すことができます。
直列化されたオブジェクトは、ファイルに書き込まれた後、そのファイルから読み取られて逆シリアル化されます。つまり、オブジェクトとそのデータを表す型情報とバイトを使用して、オブジェクトをメモリに再作成できます。
これに関するチュートリアルが必要な場合は、以下を参照してください。
Javaによる直列化(ブログ記事)
他のクラスの変数を取得(スタックオーバーフロー)
D. CommonUtilities
プロジェクトで頻繁に必要となる一般的なデータを含めることができるクラスを自分で作成することができます。
サンプル
public class CommonUtilities {
public static String className = "CommonUtilities";
}
E. インテントを介したデータの受け渡し
データを渡すこのオプションについては、チュートリアルAndroid - Parcelableクラスを使用してアクティビティ間で受け渡すデータを参照してください。
以下のようにあなた自身のクラスCustomer
を作成します:
import import Java.io.Serializable;
public class Customer implements Serializable
{
private String name;
private String city;
public Customer()
{
}
public Customer(String name, String city)
{
this.name= name;
this.city=city;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String getCity()
{
return city;
}
public void setCity(String city)
{
this.city= city;
}
}
あなたのonCreate()
メソッドで
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_top);
Customer cust=new Customer();
cust.setName("abc");
cust.setCity("xyz");
Intent intent=new Intent(abc.this,xyz.class);
intent.putExtra("bundle",cust);
startActivity(intent);
}
xyz activity
クラスでは、次のコードを使用する必要があります。
Intent intent=getIntent();
Customer cust=(Customer)intent.getSerializableExtra("bundle");
textViewName.setText(cust.getName());
textViewCity.setText(cust.getCity());
public class MyClass implements Serializable{
Here is your instance variable
}
今度はこのクラスのオブジェクトをstartActivityに渡します。単にこれを使う:
Bundle b = new Bundle();
b.putSerializable("name", myClassObject);
intent.putExtras(b);
MyClassがSerializable
を実装しているので、これはここで動作します。
最善の方法は、(Customerの場合)型 'Customer'の静的変数を保持するクラスを(Controlという)クラスに含めることです。アクティビティAの変数を初期化します。
例えば:
Control.Customer = CustomerClass;
次にアクティビティBに進み、それをControlクラスから取得します。変数を使用した後にnullを代入することを忘れないでください。そうしないとメモリが無駄になります。
Samuhが説明した方法を使用することを選択した場合は、プリミティブ値のみを送信できることを忘れないでください。つまり、解析可能な値です。そのため、あなたのオブジェクトが複雑なオブジェクトを含んでいる場合、これらは続きません。たとえば、Bitmap、HashMapなどの変数です。これらは意図的に渡すのが難しいです。
一般的に、String、int、booleanなどのように、基本データ型のみをエクストラとして送信することをお勧めします。あなたの場合は、String fname
、String lname
、int age
、およびString address
です。
私の意見: ContentProvider 、 SDCard などを実装することで、より複雑なオブジェクトをよりよく共有できます。 静的変数 を使用することも可能ですが、これはすぐにエラーが発生しやすいコードにつながります。 ..
しかし、これも私の主観的な意見です。
あるアクティビティから別のアクティビティへデータを送信するためにparcelableを使用しています。これが私のプロジェクトでうまく動作する私のコードです。
public class Channel implements Serializable, Parcelable {
/** */
private static final long serialVersionUID = 4861597073026532544L;
private String cid;
private String uniqueID;
private String name;
private String logo;
private String thumb;
/**
* @return The cid
*/
public String getCid() {
return cid;
}
/**
* @param cid
* The cid to set
*/
public void setCid(String cid) {
this.cid = cid;
}
/**
* @return The uniqueID
*/
public String getUniqueID() {
return uniqueID;
}
/**
* @param uniqueID
* The uniqueID to set
*/
public void setUniqueID(String uniqueID) {
this.uniqueID = uniqueID;
}
/**
* @return The name
*/
public String getName() {
return name;
}
/**
* @param name
* The name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* @return the logo
*/
public String getLogo() {
return logo;
}
/**
* @param logo
* The logo to set
*/
public void setLogo(String logo) {
this.logo = logo;
}
/**
* @return the thumb
*/
public String getThumb() {
return thumb;
}
/**
* @param thumb
* The thumb to set
*/
public void setThumb(String thumb) {
this.thumb = thumb;
}
public Channel(Parcel in) {
super();
readFromParcel(in);
}
public static final Parcelable.Creator<Channel> CREATOR = new Parcelable.Creator<Channel>() {
public Channel createFromParcel(Parcel in) {
return new Channel(in);
}
public Channel[] newArray(int size) {
return new Channel[size];
}
};
public void readFromParcel(Parcel in) {
String[] result = new String[5];
in.readStringArray(result);
this.cid = result[0];
this.uniqueID = result[1];
this.name = result[2];
this.logo = result[3];
this.thumb = result[4];
}
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel dest, int flags) {
dest.writeStringArray(new String[] { this.cid, this.uniqueID,
this.name, this.logo, this.thumb});
}
}
アクティビティでは次のように使用します。
Bundle bundle = new Bundle();
bundle.putParcelableArrayList("channel",(ArrayList<Channel>) channels);
Intent intent = new Intent(ActivityA.this,ActivityB.class);
intent.putExtras(bundle);
startActivity(intent);
ActivityBでは、データを取得するためにこのように使用します。
Bundle getBundle = this.getIntent().getExtras();
List<Channel> channelsList = getBundle.getParcelableArrayList("channel");
あなたはそのクラスを使うことを試みることができます。 1つのプロセスの外では使用できないという制限があります。
一つの活動:
final Object obj1 = new Object();
final Intent in = new Intent();
in.putExtra(EXTRA_TEST, new Sharable(obj1));
その他の活動
final Sharable s = in.getExtras().getParcelable(EXTRA_TEST);
final Object obj2 = s.obj();
public final class Sharable implements Parcelable {
private Object mObject;
public static final Parcelable.Creator < Sharable > CREATOR = new Parcelable.Creator < Sharable > () {
public Sharable createFromParcel(Parcel in ) {
return new Sharable( in );
}
@Override
public Sharable[] newArray(int size) {
return new Sharable[size];
}
};
public Sharable(final Object obj) {
mObject = obj;
}
public Sharable(Parcel in ) {
readFromParcel( in );
}
Object obj() {
return mObject;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(final Parcel out, int flags) {
final long val = SystemClock.elapsedRealtime();
out.writeLong(val);
put(val, mObject);
}
private void readFromParcel(final Parcel in ) {
final long val = in .readLong();
mObject = get(val);
}
/////
private static final HashMap < Long, Object > sSharableMap = new HashMap < Long, Object > (3);
synchronized private static void put(long key, final Object obj) {
sSharableMap.put(key, obj);
}
synchronized private static Object get(long key) {
return sSharableMap.remove(key);
}
}
このアクティビティから別のアクティビティを開始し、Bundle Objectを介してパラメータを渡します。
Intent intent = new Intent(getBaseContext(), YourActivity.class);
intent.putExtra("USER_NAME", "[email protected]");
startActivity(intent);
別の活動に関するデータを取得する(YourActivity)
String s = getIntent().getStringExtra("USER_NAME");
これは単純な種類のデータ型では問題ありません。しかし、もしあなたがアクティビティの間に複雑なデータを渡したいのであれば。 Uそれを最初にシリアル化する必要があります。
ここに私達に従業員モデルがあります
class Employee{
private String empId;
private int age;
print Double salary;
getters...
setters...
}
あなたはこのような複雑なデータをシリアル化するためにGoogleが提供するGson libを使うことができます。
String strEmp = new Gson().toJson(emp);
Intent intent = new Intent(getBaseContext(), YourActivity.class);
intent.putExtra("EMP", strEmp);
startActivity(intent);
Bundle bundle = getIntent().getExtras();
String empStr = bundle.getString("EMP");
Gson gson = new Gson();
Type type = new TypeToken<Employee>() {
}.getType();
Employee selectedEmp = gson.fromJson(empStr, type);
この問題は別のStack Overflowの質問でも議論されています。 Serializableを使ってインテントを通してデータを渡す への解決策を見てください。重要な点は、必要なデータをBundle
内に格納するIntent
オブジェクトを使用することです。
Bundle bundle = new Bundle();
bundle.putSerializable(key1, value1);
bundle.putSerializable(key2, value2);
bundle.putSerializable(key3, value3);
intent.putExtras(bundle);
値を抽出するには
Bundle bundle = new Bundle();
for (String key : bundle.keySet()) {
value = bundle.getSerializable(key));
}
Serializable
の利点はその単純さです。ただし、Parcelable
はAndroid専用に設計されており、Parcelable
よりも効率的であるため、転送するデータが多数ある場合はSerializable
メソッドの使用を検討する必要があります。あなたはParcelable
クラスを作成することができます:
Beanクラスのようなクラスを作成してSerializable
インターフェースを実装します。それからintent
メソッドを通してそれを渡すことができます、例えば:
intent.putExtra("class", BeanClass);
それから他の活動からそれを得なさい、例えば:
BeanClass cb = intent.getSerializableExtra("class");
このようにカスタムクラスに2つのメソッドを作成します。
public class Qabir {
private int age;
private String name;
Qabir(){
}
Qabir(int age,String name){
this.age=age; this.name=name;
}
// method for sending object
public String toJSON(){
return "{age:" + age + ",name:\"" +name +"\"}";
}
// method for get back original object
public void initilizeWithJSONString(String jsonString){
JSONObject json;
try {
json =new JSONObject(jsonString );
age=json.getInt("age");
name=json.getString("name");
} catch (JSONException e) {
e.printStackTrace();
}
}
}
今すぐあなたの送り主の活動はこれのようにします
Qabir q= new Qabir(22,"KQ");
Intent in=new Intent(this,SubActivity.class);
in.putExtra("obj", q.toJSON());
startActivity( in);
そしてあなたの受信機で
Qabir q =new Qabir();
q.initilizeWithJSONString(getIntent().getStringExtra("obj"));
ええ、静的オブジェクトを使うことは、カスタムの直列化不可能なオブジェクトを使ってこれを行う最も簡単な方法です。
AndroidのActivityオブジェクトは破棄して再構成することができます。それで、あなたは 彼ら - あるいは彼らがつくるどんなオブジェクト - を見るために別のアプローチを使う必要があるでしょう !!! - アップつまり、静的クラス参照として渡すことができますが、オブジェクトハンドル(SmalltalkのようにJavaはこれらの「参照」と呼びますが、Cまたはアセンブリの意味での参照ではありません)は後で無効になる可能性があります。 Android OEのいずれかの活動は消滅し、後で再構成することができます。
最初の質問は「Androidでオブジェクトをあるアクティビティから別のアクティビティに渡す方法」であり、誰もそれに答えていません。確かに、シリアル化(Serializable、Parcelable、JSONから)、およびオブジェクトのデータのコピーを渡すことで、同じデータを持つ新しいオブジェクトを作成できます。しかし、同じ参照/ハンドルはありません。また、他の多くの人があなたが静的ストアに参照を保存できると述べました。 AndroidがあなたのアクティビティをonDestroyすることを決めない限り、それはうまくいくでしょう。
そのため、元の質問を本当に解決するには、静的ルックアップが必要になります。さらに、各オブジェクトは、再作成されたときに、その参照を更新します。例えば。 onCreateが呼び出されると、各Androidアクティビティは自動的に再リストされます。また、一部の人がタスクリストを使用して名前でアクティビティを検索する方法も確認できます。 (システムはスペースを節約するためにアクティビティのこのインスタンスを一時的に破棄しています。getRunningTasks。タスクリストは事実上各アクティビティの最新のオブジェクトインスタンスの特殊なリストです)。
参考のため:
停止: "アクティビティは他のアクティビティによって完全に隠されています(アクティビティは"バックグラウンド "になっています)。停止したアクティビティもまだ生きています( Activityオブジェクトはメモリに保持されます しかし、ウィンドウマネージャには接続されていません。ただし、ユーザには表示されなくなり、他の場所でメモリが必要になったときにシステムによって強制終了される可能性があります。」
"onDestroy"システムは一時的に このインスタンスを破棄しています スペースを節約するためのアクティビティです。 "
したがって、メッセージバスは実行可能なソリューションです。それは基本的に "パント"です。オブジェクトを参照するのではなく、次に、SequentialCodeの代わりにMessagePassingを使用するようにデザインを再設計します。指数関数的にデバッグするのは難しいです。しかし、それはあなたがこれらの種類のOperatingEnvironmentの理解を無視することを可能にします。実際には、各オブジェクトメソッドのアクセスは反転されているため、呼び出し元はMessageをポストし、オブジェクト自体はそのメッセージのハンドラを定義します。より多くのコードがありますが、Android OEの制限により堅牢にすることができます。
あなたが望むのが一番上のアクティビティ(どこでも "Context"が必要とされるためにAndroidアプリで典型的なこと)だけであれば、そのonResumeが呼び出されるときはいつでも各グローバルアクティビティを静的グローバル空間でそれ自身を "top"としてリストできます。それからあなたのAlertDialogあるいは文脈を必要とするものは何でもそこからそれをつかむことができます。また、グローバルを使用するのは少々手間がかかりますが、コンテキストを上下左右に渡すのを簡単にすることができます。もちろん、MessageBusを使用する場合はIT IS globalを使用します。
私は静的が悪いことを知っていますが、私たちはここでそれを使わざるを得ないようです。 parceables/seriazablesの問題は、2つのアクティビティに同じオブジェクトのインスタンスが重複していることです。メモリとCPUが無駄になります。
public class IntentMailBox {
static Queue<Object> content = new LinkedList<Object>();
}
コーリング活動
IntentMailBox.content.add(level);
Intent intent = new Intent(LevelsActivity.this, LevelActivity.class);
startActivity(intent);
呼び出されたアクティビティ( onCreate() および onResume() は、システムがアクティビティを破棄して再作成したときに複数回呼び出されることがあります)
if (IntentMailBox.content.size()>0)
level = (Level) IntentMailBox.content.poll();
else
// Here you reload what you have saved in onPause()
もう1つの方法は、そのクラスに渡すクラスの静的フィールドを宣言することです。それはこの目的のためだけに役立つでしょう。アプリパッケージはシステムによってメモリからアンロードされ、後で再ロードされるため、onCreateではnullになる可能性があることを忘れないでください。
まだアクティビティのライフサイクルを処理する必要があることを念頭に置いて、そのままの状態では面倒な、すべてのデータを直接共有設定に書き込むことをお勧めします。
上記の答えはほとんどすべて正しいが、それらの答えを理解していない人のためにAndroidは強力なクラスを持っている Intent それを使ってあなたは活動だけではなく私たちはContetnResolverクラス(Intent)を使用しています。あなたの活動の中であなたは意図を築きます
Intent intent = new Intent(context,SomeActivity.class);
intent.putExtra("key",value);
startActivity(intent);
あなたの受け取り活動には
public class SomeActivity extends AppCompactActivity {
public void onCreate(...){
...
SomeObject someObject = getIntent().getExtras().getParceable("key");
}
}
アクティビティ間で共有するには、オブジェクトにParceableまたはSerializableインタフェースを実装する必要があります。オブジェクトに Parcealbe ではなく Parcealbe を実装するのは困難です。Androidがこのために特にプラグインを持っているのはそのためです。ダウンロードして使用する
あるアクティビティから別のアクティビティにオブジェクトを渡します。
(1)ソースアクティビティ
Intent ii = new Intent(examreport_select.this,
BarChartActivity.class);
ii.putExtra("IntentExamResultDetail",
(Serializable) your List<ArraList<String>> object here);
startActivity(ii);
(2)行き先活動
List<ArrayList<String>> aa = (List<ArrayList<String>>) getIntent()
.getSerializableExtra("IntentExamResultDetail");
オブジェクトをあるアクティビティから別のアクティビティに渡すことができます。
SupplierDetails poSuppliersDetails = new SupplierDetails();
poSuppliersDetails
の中にはいくつかの値があります。今、私はこのオブジェクトをターゲットアクティビティに送信しています:
Intent iPODetails = new Intent(ActivityOne.this, ActivityTwo.class);
iPODetails.putExtra("poSuppliersDetails", poSuppliersDetails);
ACtivityTwoでこれを取得する方法:
private SupplierDetails supplierDetails;
supplierDetails =(SupplierDetails) getIntent().getSerializableExtra("poSuppliersDetails");
あるアクティビティを別のアクティビティに渡します。
startActivity(new Intent(getBaseContext(),GetActivity.class).putExtra("passingkey","passingvalue"));
値を取得します:
String myvalue= getIntent().getExtras("passingkey");
私はオブジェクトを転送するためにPacelableまたはSerializableで設定していましたが、オブジェクト(モデル)に他の変数を追加するときはいつでも、それをすべて登録する必要があります。とても不便です。
アクティビティ間やフラグメント間でオブジェクトを転送するのはとても簡単です。
私はいつも、これが他のアクティビティのメソッドを呼び出すのと同じくらい単純にならない理由を疑問に思いました。私は最近それをそれとほとんど同じくらい簡単にするユーティリティライブラリを書きました。あなたはここでそれをチェックすることができます( https://github.com/noxiouswinter/gnlib_Android/wiki/ignlauncher )。
GNLauncher を使用すると、必要なデータをパラメータとして使用してアクティビティ内の関数を呼び出すのと同じくらい簡単に、別のアクティビティなどからアクティビティにオブジェクト/データを送信できます。それは型安全を導入し、直列化しなければならない、文字列キーを使用して意図にアタッチする、そして反対側でそれを元に戻すというすべての面倒を取り除きます。
起動するアクティビティで呼び出したいメソッドを使用してインタフェースを定義します。
public interface IPayload {
public void sayHello(String name, int age);
}
起動するActivityに上記のインターフェースを実装します。アクティビティの準備ができたらGNLauncherにも通知してください。
public class Activity_1 extends Activity implements IPayload {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Notify GNLauncher when the Activity is ready.
GNLauncher.get().ping(this);
}
@Override
public void sayHello(String name, int age) {
Log.d("gnlib_test", "Hello " + name + "! \nYour age is: " + age);
}
}
もう一方のアクティビティでは、上記のアクティビティへのプロキシを取得し、必要なパラメータを使用して任意のメソッドを呼び出します。
public class Activity_2 extends Activity {
public void onClick(View v) {
((IPayload)GNLauncher.get().getProxy(this, IPayload.class, Activity_1.class)).sayHello(name, age);
}
}
最初のアクティビティが起動され、必要なパラメータを使ってメソッドが呼び出されます。
依存関係を追加する方法については https://github.com/noxiouswinter/gnlib_Android/wiki #prerequisites を参照してください。