गतिविधि और सेवा के बीच संचार

किसी तरह मेरे पास सेवा से गतिविधि तक डेटा स्थानांतरित करने का कार्य था। मानक एसडीके में एक समाधान की खोज शुरू हुई, लेकिन चूंकि कोई समय नहीं था, इसलिए डेटाबेस का उपयोग करने के रूप में एक बुरा समाधान बनाया गया था। लेकिन सवाल खुला था और थोड़ी देर बाद मैंने एसडीके के पास मैसेज, हैंडलर, मैसेंजर कक्षाओं का उपयोग करते हुए अधिक सटीक तरीका निकाला।

विचार


हमें गतिविधि से सेवा में डेटा स्थानांतरित करने की आवश्यकता है और इसके विपरीत। हम यह कैसे करते हैं? हमारी समस्या को हल करने के लिए, हमारे पास पहले से ही वह सब कुछ है जो हमें चाहिए। सभी की जरूरत है कि सेवा को आत्मीयता से बांधने के लिए, बिंदासवर्क का उपयोग करके, आवश्यक पैरामीटर और मैजिक कक्षाओं का उपयोग करने के रूप में थोड़ा सा जादू पास करें। और मैसेज का उपयोग मैसेज इंस्टेंस वेरिएबल और विशेष रूप से, रिप्लाई में करना है। हमें इस चर की आवश्यकता है ताकि हम गतिविधि से मेसेंजर सेवा के उदाहरण तक पहुंच सकें और सेवा में, मेसेंजर गतिविधि के उदाहरण। वास्तव में, इतना आसान नहीं है। कम से कम मेरे लिए बहुत उपहारित मन नहीं है। भाग में, मैं पहले से मौजूद दस्तावेज को सुधार रहा हूं - सेवाएं । मैं गतिविधि में एक कनेक्शन जोड़कर, डेटा को आगे और पीछे स्थानांतरित कर रहा हूं, जो कि प्रलेखन में नहीं है। इसके अलावा, StackOverflow पर एक अच्छा उदाहरण है। किसी भी मामले में, मुझे उम्मीद है कि लेख कम से कम किसी के लिए उपयोगी होगा और मैंने व्यर्थ में काम नहीं किया।

उदाहरण


एक उदाहरण के रूप में, हम एक ऐसी सेवा लागू करते हैं जो काउंटर वैल्यू को बढ़ाएगी और घटाएगी और परिणाम को गतिविधि पर लौटाएगी, पाठ दृश्य में। मैं लेआउट कोड को छोड़ दूंगा, क्योंकि दो बटन और एक टेक्स्ट फ़ील्ड है - सब कुछ सरल है।

कार्यान्वयन


मैं पूर्ण सक्रियण कोड दूंगा:

public class MainActivity extends Activity { public static final String TAG = "TestService"; TestServiceConnection testServConn; TextView testTxt; final Messenger messenger = new Messenger(new IncomingHandler()); Messenger toServiceMessenger; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); testTxt = (TextView)findViewById(R.id.test_txt); bindService(new Intent(this, TestService.class), (testServConn = new TestServiceConnection()), Context.BIND_AUTO_CREATE); } @Override public void onDestroy(){ super.onDestroy(); unbindService(testServConn); } public void countIncrClick(View button){ Message msg = Message.obtain(null, TestService.COUNT_PLUS); msg.replyTo = messenger; try { toServiceMessenger.send(msg); } catch (RemoteException e) { e.printStackTrace(); } } public void countDecrClick(View button){ Message msg = Message.obtain(null, TestService.COUNT_MINUS); msg.replyTo = messenger; try { toServiceMessenger.send(msg); } catch (RemoteException e) { e.printStackTrace(); } } private class IncomingHandler extends Handler { @Override public void handleMessage(Message msg){ switch (msg.what) { case TestService.GET_COUNT: Log.d(TAG, "(activity)...get count"); testTxt.setText(""+msg.arg1); break; } } } private class TestServiceConnection implements ServiceConnection { @Override public void onServiceConnected(ComponentName name, IBinder service) { toServiceMessenger = new Messenger(service); //    Message msg = Message.obtain(null, TestService.SET_COUNT); msg.replyTo = messenger; msg.arg1 = 0; //  try { toServiceMessenger.send(msg); } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onServiceDisconnected(ComponentName name) { } } } 


मैं समझा दूंगा। एक गतिविधि बनाते समय, हम तुरंत सेवा से जुड़ जाते हैं, ServiceConnection इंटरफ़ेस को लागू करते हैं और "सेट काउंटर वैल्यू" सेवा को एक संदेश भेजते हैं, शून्य पास करते हैं और toServiceMessanger बनाते हैं, जो निर्माणकर्ता को IBinder इंटरफ़ेस पास करते हैं। वैसे, आपको इस उदाहरण को सेवा में वापस करना होगा, अन्यथा एनपीई होगा। इस वर्ग का उपयोग करते हुए, हम सेवा को संदेश भेजते हैं। और यहां यह जादू है - उत्तर-चर में हम मैसेंजर के हमारे अन्य उदाहरण को सहेजते हैं - वह जो सर्वर से प्रतिक्रिया प्राप्त करता है और यह इसके माध्यम से है कि गतिविधि के साथ कनेक्शन बाहर किया जाएगा।

सेवा से एक संदेश प्राप्त करने के लिए, हम अपने हैंडलर का उपयोग करते हैं और बस उन चरों की तलाश करते हैं जिनकी हमें आवश्यकता है और उन पर कार्रवाई करते हैं। हम बटन पर क्लिक करके (तरीके countIncrClick, countDecrClick) हम सेवा को अनुरोध भेजते हैं, चर msg.what में वांछित कार्रवाई का संकेत देते हैं।

अगला, पूर्ण सेवा कोड:

 package com.example.servicetest; import android.app.Service; import android.content.*; import android.os.*; import android.os.Process; import android.util.Log; public class TestService extends Service { public static final int COUNT_PLUS = 1; public static final int COUNT_MINUS = 2; public static final int SET_COUNT = 0; public static final int GET_COUNT = 3; int count = 0; IncomingHandler inHandler; Messenger messanger; Messenger toActivityMessenger; @Override public void onCreate(){ super.onCreate(); HandlerThread thread = new HandlerThread("ServiceStartArguments", Process.THREAD_PRIORITY_BACKGROUND); thread.start(); inHandler = new IncomingHandler(thread.getLooper()); messanger = new Messenger(inHandler); } @Override public IBinder onBind(Intent arg0) { return messanger.getBinder(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { return START_STICKY; } //   private class IncomingHandler extends Handler { public IncomingHandler(Looper looper){ super(looper); } @Override public void handleMessage(Message msg){ //super.handleMessage(msg); toActivityMessenger = msg.replyTo; switch (msg.what) { case SET_COUNT: count = msg.arg1; Log.d(MainActivity.TAG, "(service)...set count"); break; case COUNT_PLUS: count++; Log.d(MainActivity.TAG, "(service)...count plus"); break; case COUNT_MINUS: Log.d(MainActivity.TAG, "(service)...count minus"); count--; break; } //     Message outMsg = Message.obtain(inHandler, GET_COUNT); outMsg.arg1 = count; outMsg.replyTo = messanger; try { if( toActivityMessenger != null ) toActivityMessenger.send(outMsg); } catch (RemoteException e) { e.printStackTrace(); } } } } 


सभी गतिविधि में तर्क के साथ सादृश्य द्वारा। अगर मुझे कुछ समझाने की जरूरत है, तो मैं भी नहीं जानता। एकमात्र क्षण यह है कि मैं तुरंत पुनः भेजने का अनुरोध करता हूं, हैंडलमैसेज में गतिविधि के लिए, उत्तरपट्टी मैजिक चर का उपयोग करके और ऊपर के वांछित मैसेंजर को खींचकर। और दूसरा बिंदु जो मैंने पहले ही उल्लेख किया है वह है:

 @Override public IBinder onBind(Intent arg0) { return messanger.getBinder(); } 


जिसके बिना सब गिर जाएगा। यह इंटरफ़ेस का ऐसा उदाहरण है जिसे ServiceConnection को पास किया जाएगा

निष्कर्ष


सभी में। गतिविधि और सेवा की सहभागिता का ऐसा दूरगामी उदाहरण। यह मुझे काफी गैर-तुच्छ बातचीत लगती है, हालांकि यह किसी को अन्यथा लग सकता है।

प्रोजेक्ट कोड Bitbucket पर है

पीएम में सवाल, स्पष्टीकरण आदि। कुछ पहलुओं के बारे में गलतियाँ हो सकती हैं, इसलिए लिखने और सही करने के लिए स्वतंत्र महसूस करें।
मुझे उम्मीद है कि पोस्ट habrayuzery के लिए उपयोगी थी।

Source: https://habr.com/ru/post/In157063/


All Articles