Basit ve zarif bir yöntem buldum:
- Parcelable
- Serializeable YOK
- Statik Alan YOK
- Etkinlik Otobüsü Yok
Yöntem 1
İlk etkinliğin kodu:
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);
İkinci etkinliğin kodu:
final Object objReceived = ((ObjectWrapperForBinder)getIntent().getExtras().getBinder("object_value")).getData();
Log.d(TAG, "received object=" + objReceived);
sen bulacaksın objSent
ve objReceived
aynıhashCode
, bu yüzden aynı.
Ama neden bir java nesnesini bu şekilde aktarabiliriz?
Aslında, android bağlayıcı java nesnesi için global JNI referansı oluşturacak ve bu java nesnesi için referans olmadığında bu global JNI referansını serbest bırakacaktır. binder bu global JNI başvurusunu Binder nesnesine kaydeder.
* DİKKAT: bu yöntem SADECE iki işlem aynı işlemde çalışmadığı sürece çalışır, aksi takdirde ClassCastException (ObjectWrapperForBinder) getIntent (). GetExtras (). GetBinder ("object_value") *
class ObjectWrapperForBinder tanımı
public class ObjectWrapperForBinder extends Binder {
private final Object mData;
public ObjectWrapperForBinder(Object data) {
mData = data;
}
public Object getData() {
return mData;
}
}
Yöntem 2
- gönderen için,
- java nesnenizi JNI genel başvuru tablosuna eklemek için özel yerel yöntemi kullanın (JNIEnv :: NewGlobalRef aracılığıyla)
- dönüş tamsayısını (aslında, bir işaretçi olan JNIEnv :: NewGlobalRef dönüş jobject'i, int'e güvenli bir şekilde atabiliriz) niyetinize (Intent :: putExtra aracılığıyla)
- alıcı için
- Intent'ten tamsayı alın (Intent :: getInt aracılığıyla)
- java nesnenizi JNI genel başvuru tablosundan geri yüklemek için özel yerel yöntem kullanın (JNIEnv :: NewLocalRef aracılığıyla)
- JNI genel referans tablosundan öğeyi kaldır (JNIEnv :: DeleteGlobalRef aracılığıyla),
Ancak Yöntem 2'nin küçük ama ciddi bir sorunu vardır, alıcı java nesnesini geri yükleyemezse (örneğin, java nesnesini geri yüklemeden önce bir istisna oluşur veya alıcı Etkinliği hiç mevcut değilse), java nesnesi bir yetim veya bellek sızıntısı, Yöntem 1'de bu sorun yok, çünkü android bağlayıcı bu istisnayı ele alacak
Yöntem 3
Java nesnesini uzaktan çağırmak için, java nesnesini tanımlamak için bir veri sözleşmesi / arabirimi oluşturacağız, aidl dosyasını kullanacağız
IDataContract.aidl
package com.example.objectwrapper;
interface IDataContract {
int func1(String arg1);
int func2(String arg1);
}
İlk etkinliğin kodu
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);
İkinci etkinliğin kodu:
ikinci etkinliğin başka bir işlemde çalıştığından emin olmak için AndroidManifest.xml dosyasında android: process özniteliğini boş olmayan bir işlem adına değiştirin
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();
}
Bu şekilde, farklı işlemlerde çalışsalar bile, iki etkinlik arasında bir arabirim geçirebilir ve arabirim yöntemini uzaktan çağırabiliriz
Yöntem 4
yöntem 3 yeterince basit görünmüyor çünkü bir aidl arabirimi uygulamalıyız. Sadece basit bir görev yapmak istiyorsanız ve yöntem dönüş değeri gereksizse, android.os.Messenger'ı kullanabiliriz.
İlk faaliyetin kodu (gönderen):
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)));
}
}
İkinci etkinliğin kodu (alıcı):
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();
}
}
}
Tüm Messenger.send, bir İşleyicide zaman uyumsuz ve sıralı olarak yürütülür.
Aslında, android.os.Messenger da bir aidl arayüzüdür, android kaynak kodunuz varsa, IMessenger.aidl adlı bir dosya bulabilirsiniz
package android.os;
import android.os.Message;
/** @hide */
oneway interface IMessenger {
void send(in Message msg);
}