मुझे एक सरल और सुरुचिपूर्ण विधि मिली:
- न पार्सलबल
- कोई सीरियल नहीं
- कोई स्थैतिक क्षेत्र
- कोई इवेंट बस नहीं
विधि 1
पहली गतिविधि के लिए कोड:
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);
दूसरी गतिविधि के लिए कोड:
final Object objReceived = ((ObjectWrapperForBinder)getIntent().getExtras().getBinder("object_value")).getData();
Log.d(TAG, "received object=" + objReceived);
आपको वही मिलेगा objSent
और होगा , इसलिए वे समान हैं।objReceived
hashCode
लेकिन हम इस तरह से एक जावा ऑब्जेक्ट क्यों पारित कर सकते हैं?
दरअसल, android binder java object के लिए Global JNI Reference बनाएगी और इस JNI ऑब्जेक्ट के लिए कोई संदर्भ नहीं होने पर यह Global JNI संदर्भ जारी करेगी। बाइंडर इस वैश्विक JNI संदर्भ को Binder ऑब्जेक्ट में बचाएगा।
* चेतावनी: यह विधि केवल तब तक काम करती है जब तक कि दो गतिविधियाँ एक ही प्रक्रिया में न चलें, अन्यथा ClassCastException को (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;
}
}
विधि 2
- प्रेषक के लिए,
- JNI वैश्विक संदर्भ तालिका (JNIEnv :: NewGlobalRef) के माध्यम से अपने जावा ऑब्जेक्ट को जोड़ने के लिए कस्टम देशी विधि का उपयोग करें
- रिटर्न पूर्णांक (वास्तव में, JNIEnv :: NewGlobalRef रिटर्न जॉबजेक्ट, जो एक पॉइंटर है, हम इसे आपके इंटेंट तक सुरक्षित रूप से डाल सकते हैं) (इंटेंट :: putExtra के माध्यम से)
- रिसीवर के लिए
- आशय से पूर्णांक प्राप्त करें (आशय :: getInt के माध्यम से)
- JNI वैश्विक संदर्भ तालिका (JNIEnv :: NewLocalRef के माध्यम से) से अपने जावा ऑब्जेक्ट को पुनर्स्थापित करने के लिए कस्टम मूल विधि का उपयोग करें
- JNI वैश्विक संदर्भ तालिका से आइटम निकालें (JNIEnv :: DeleteGlobalRef के माध्यम से),
लेकिन विधि 2 में थोड़ा लेकिन गंभीर मुद्दा है, यदि रिसीवर जावा ऑब्जेक्ट को पुनर्स्थापित करने में विफल रहता है (उदाहरण के लिए, जावा ऑब्जेक्ट को पुनर्स्थापित करने से पहले कुछ अपवाद होता है, या रिसीवर गतिविधि बिल्कुल भी मौजूद नहीं है), तो जावा ऑब्जेक्ट एक बन जाएगा अनाथ या स्मृति रिसाव, विधि 1 में यह समस्या नहीं है, क्योंकि एंड्रॉइड बाइंडर इस अपवाद को संभाल लेगा
विधि 3
जावा ऑब्जेक्ट को दूरस्थ रूप से आह्वान करने के लिए, हम जावा ऑब्जेक्ट का वर्णन करने के लिए एक डेटा अनुबंध / इंटरफ़ेस बनाएंगे, हम सहायता फ़ाइल का उपयोग करेंगे
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);
दूसरी गतिविधि के लिए कोड:
Android बदलें: प्रक्रिया की विशेषता AndroidManifest.xml में एक अन्य प्रक्रिया में चलने वाली दूसरी गतिविधि को सुनिश्चित करने के लिए एक गैर-रिक्त प्रक्रिया नाम के लिए।
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();
}
इस प्रकार, हम दो गतिविधियों के बीच एक इंटरफ़ेस पास कर सकते हैं भले ही वे अलग-अलग प्रक्रिया में चलें, और इंटरफ़ेस विधि को दूरस्थ रूप से कॉल करें
विधि 4
पद्धति 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)));
}
}
दूसरी गतिविधि के लिए कोड (रिसीवर):
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 एक हैंडलर में अतुल्यकालिक और क्रमिक रूप से निष्पादित करेंगे।
वास्तव में, android.os.Messenger भी एक सहायक इंटरफ़ेस है, यदि आपके पास Android स्रोत कोड है, तो आप IMessenger.aidl नामक एक फ़ाइल पा सकते हैं
package android.os;
import android.os.Message;
/** @hide */
oneway interface IMessenger {
void send(in Message msg);
}