Saya menemukan metode sederhana & elegan:
- TIDAK ADA Bingkisan
- TIDAK Serializable
- TANPA Bidang Statis
- Tidak Ada Bus Acara
Metode 1
Kode untuk aktivitas pertama:
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);
Kode untuk aktivitas kedua:
final Object objReceived = ((ObjectWrapperForBinder)getIntent().getExtras().getBinder("object_value")).getData();
Log.d(TAG, "received object=" + objReceived);
Anda akan menemukan objSent
& objReceived
memiliki yang sama hashCode
, sehingga mereka identik.
Tapi mengapa kita bisa melewatkan objek java dengan cara ini?
Sebenarnya, pengikat android akan membuat referensi JNI global untuk objek java dan melepaskan referensi JNI global ini ketika tidak ada referensi untuk objek java ini. binder akan menyimpan referensi JNI global ini di objek Binder.
* HATI-HATI: metode ini HANYA berfungsi kecuali dua aktivitas berjalan dalam proses yang sama, jika tidak lempar ClassCastException di (ObjectWrapperForBinder) getIntent (). GetExtras (). GetBinder ("object_value") *
class ObjectWrapperForBinder defination
public class ObjectWrapperForBinder extends Binder {
private final Object mData;
public ObjectWrapperForBinder(Object data) {
mData = data;
}
public Object getData() {
return mData;
}
}
Metode 2
- untuk pengirim,
- menggunakan metode asli kustom untuk menambahkan objek java Anda ke tabel referensi global JNI (via JNIEnv :: NewGlobalRef)
- letakkan integer pengembalian (sebenarnya, JNIEnv :: NewGlobalRef jobject kembali, yang merupakan pointer, kita dapat melemparkannya ke int dengan aman) ke Intent Anda (melalui Intent :: putExtra)
- untuk penerima
- dapatkan integer dari Intent (via Intent :: getInt)
- menggunakan metode asli kustom untuk mengembalikan objek java Anda dari tabel referensi global JNI (via JNIEnv :: NewLocalRef)
- hapus item dari tabel referensi global JNI (via JNIEnv :: DeleteGlobalRef),
Tetapi Metode 2 memiliki masalah kecil tapi serius, jika penerima gagal mengembalikan objek java (misalnya, beberapa pengecualian terjadi sebelum mengembalikan objek java, atau Kegiatan penerima tidak ada sama sekali), maka objek java akan menjadi anak yatim atau kehabisan memori, Metode 1 tidak memiliki masalah ini, karena pengikat android akan menangani pengecualian ini
Metode 3
Untuk memohon objek java dari jarak jauh, kami akan membuat kontrak data / antarmuka untuk menggambarkan objek java, kami akan menggunakan file aidl
IDataContract.aidl
package com.example.objectwrapper;
interface IDataContract {
int func1(String arg1);
int func2(String arg1);
}
Kode untuk aktivitas pertama
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);
Kode untuk aktivitas kedua:
ubah atribut android: process di AndroidManifest.xml menjadi nama proses yang tidak kosong untuk memastikan aktivitas kedua berjalan di proses lain
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();
}
Dengan cara ini, kita dapat melewati antarmuka antara dua aktivitas meskipun mereka berjalan dalam proses yang berbeda, dan memanggil metode antarmuka dari jarak jauh
Metode 4
Metode 3 tampaknya tidak cukup sederhana karena kita harus mengimplementasikan antarmuka Aidl. Jika Anda hanya ingin melakukan tugas sederhana dan nilai metode pengembalian tidak diperlukan, kita dapat menggunakan android.os.Messenger
Kode untuk aktivitas pertama (pengirim):
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)));
}
}
Kode untuk aktivitas kedua (penerima):
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();
}
}
}
Semua Messenger.send akan mengeksekusi dalam Handler secara tidak sinkron dan berurutan.
Sebenarnya, android.os.Messenger juga merupakan antarmuka Aidl, jika Anda memiliki kode sumber android, Anda dapat menemukan file bernama IMessenger.aidl
package android.os;
import android.os.Message;
/** @hide */
oneway interface IMessenger {
void send(in Message msg);
}