दिलचस्प पोस्ट
jQuery – इवेंट बंद होने के बाद मैं कैसे अस्थायी रूप से ऑनक्लिक ईवेंट श्रोता को अक्षम कर सकता / सकती हूं? डेल्फी में पैच की नियमित कॉल गुणों की फ़ाइल का उपयोग करके जावा लॉगिंग कैसे सेट अप करें? (java.util.logging) फ़ंक्शन पॉइंटर्स, क्लोज़र और लैम्ब्डा मैं "प्रकार त्रुटि" क्यों देख रहा हूं: स्ट्रिंग इंडेक्स पूर्णांक होना चाहिए "? जैक्सन के साथ सीरियलिंग (जेएसओएन) – "कोई सीरियलइज़र नहीं मिला"? जावास्क्रिप्ट में घुंघराले ब्रेसिज़ क्या मतलब है? एंड्रॉइड स्टूडियो में जेएनआई और ग्रेडल LINQ का सबसे कठिन या सबसे गलतफहमी वाला पहलू क्या है? MySQL – क्या मैं चलाने के लिए एक क्वेरी के लिए अधिकतम समय सीमा सीमित कर सकता हूँ? एक रिवेर्जेसिअल कंसल्टेंट में एक आश्रित संपत्ति को स्टोर-जनरेटेड कॉलम में मैप किया जाता है महत्वपूर्ण स्तर के साथ बॉक्स प्लॉट कैसे आकर्षित करें? बूस्ट के साथ INI फ़ाइल को पार्स करने के लिए कैसे करें एक समारोह से संग्रहित प्रक्रिया निष्पादित करें कैसे एक वस्तु पर पिछले उम्मीदों को साफ करने के लिए?

सेवा से एंड्रॉइड अपडेट गतिविधि यूआई

मेरे पास एक सेवा है जो हर समय नए कार्य की जांच कर रही है। यदि नया कार्य है, तो मैं उस जानकारी को दिखाने के लिए गतिविधि UI को रीफ़्रेश करना चाहता हूं। मुझे https://github.com/commonsguy/cw-andtutorials/tree/master/18-LocalService/ यह उदाहरण मिला। क्या यह एक अच्छा दृष्टिकोण है? कोई अन्य उदाहरण?

धन्यवाद।

Solutions Collecting From Web of "सेवा से एंड्रॉइड अपडेट गतिविधि यूआई"

मेरे मूल उत्तर के लिए नीचे देखें – यह पैटर्न अच्छी तरह से काम किया है, लेकिन हाल ही में मैंने सेवा / गतिविधि संचार के लिए एक अलग दृष्टिकोण का उपयोग करना शुरू कर दिया है:

  • एक बाध्य सेवा का उपयोग करें जो गतिविधि को सेवा के लिए एक सीधा संदर्भ प्राप्त करने में सक्षम बनाता है, इस प्रकार इंटेंट्स का उपयोग करने के बजाय उस पर सीधे कॉल की अनुमति देता है।
  • अतुल्यकालिक कार्यों को निष्पादित करने के लिए RxJava का उपयोग करें।

  • अगर सेवा को पृष्ठभूमि के संचालन को जारी रखने की जरूरत है, कोई गतिविधि नहीं चल रही है, तब भी आवेदन कक्षा से सेवा शुरू करें ताकि यह अनबाउंड हो जाने पर रोके न जाए।

StartService () / लोकल ब्रॉडकास्ट तकनीक की तुलना में इस दृष्टिकोण में मुझे मिले लाभ

  • पार्सलेबल को कार्यान्वित करने के लिए डेटा ऑब्जेक्ट्स की कोई ज़रूरत नहीं है – यह मेरे लिए विशेष रूप से महत्वपूर्ण है क्योंकि अब मैं एंड्रॉइड और आईओएस (रोबोइम का उपयोग कर) के बीच कोड साझा कर रहा हूं।
  • RxJava डिब्बाबंद (और क्रॉस-प्लेटफॉर्म) शेड्यूलिंग, और अनुक्रमिक अतुल्यकालिक कार्यों की आसान संरचना प्रदान करता है।
  • यह लोकल ब्रॉडकास्ट के उपयोग से ज्यादा कुशल होना चाहिए, हालांकि आरएक्सजावा का उपयोग करने के ऊपर की ओर पलट सकता है।

कुछ उदाहरण कोड पहले सेवा:

public class AndroidBmService extends Service implements BmService { private static final int PRESSURE_RATE = 500000; // microseconds between pressure updates private SensorManager sensorManager; private SensorEventListener pressureListener; private ObservableEmitter<Float> pressureObserver; private Observable<Float> pressureObservable; public class LocalBinder extends Binder { public AndroidBmService getService() { return AndroidBmService.this; } } private IBinder binder = new LocalBinder(); @Nullable @Override public IBinder onBind(Intent intent) { logMsg("Service bound"); return binder; } @Override public int onStartCommand(Intent intent, int flags, int startId) { return START_NOT_STICKY; } @Override public void onCreate() { super.onCreate(); sensorManager = (SensorManager)getSystemService(SENSOR_SERVICE); Sensor pressureSensor = sensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE); if(pressureSensor != null) sensorManager.registerListener(pressureListener = new SensorEventListener() { @Override public void onSensorChanged(SensorEvent event) { if(pressureObserver != null) { float lastPressure = event.values[0]; float lastPressureAltitude = (float)((1 - Math.pow(lastPressure / 1013.25, 0.190284)) * 145366.45); pressureObserver.onNext(lastPressureAltitude); } } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { } }, pressureSensor, PRESSURE_RATE); } @Override public Observable<Float> observePressure() { if(pressureObservable == null) { pressureObservable = Observable.create(emitter -> pressureObserver = emitter); pressureObservable = pressureObservable.share(); } return pressureObservable; } @Override public void onDestroy() { if(pressureListener != null) sensorManager.unregisterListener(pressureListener); } } 

और एक गतिविधि जो सेवा से जुड़ी हुई है और दबाव ऊंचाई के अद्यतन प्राप्त करती है:

 public class TestActivity extends AppCompatActivity { private ContentTestBinding binding; private ServiceConnection serviceConnection; private AndroidBmService service; private Disposable disposable; @Override protected void onDestroy() { if(disposable != null) disposable.dispose(); unbindService(serviceConnection); super.onDestroy(); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); binding = DataBindingUtil.setContentView(this, R.layout.content_test); serviceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName componentName, IBinder iBinder) { logMsg("BlueMAX service bound"); service = ((AndroidBmService.LocalBinder)iBinder).getService(); disposable = service.observePressure() .observeOn(AndroidSchedulers.mainThread()) .subscribe(altitude -> binding.altitude.setText( String.format(Locale.US, "Pressure Altitude %d feet", altitude.intValue()))); } @Override public void onServiceDisconnected(ComponentName componentName) { logMsg("Service disconnected"); } }; bindService(new Intent( this, AndroidBmService.class), serviceConnection, BIND_AUTO_CREATE); } } 

इस गतिविधि के लिए लेआउट है:

 <?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" > <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.controlj.mfgtest.TestActivity"> <TextView tools:text="Pressure" android:id="@+id/altitude" android:gravity="center_horizontal" android:layout_gravity="center_vertical" android:layout_width="match_parent" android:layout_height="wrap_content"/> </LinearLayout> </layout> 

यदि सेवा को बिना किसी बाध्य गतिविधि के पृष्ठभूमि में चलाने की जरूरत है, तो इसे Context#startService() का उपयोग करते हुए एप्लिकेशन क्लास के साथ ही OnCreate() में शुरू किया जा सकता है।


मेरा मूल उत्तर (2013 से):

आपकी सेवा में: (सीओपीए का इस्तेमाल नीचे दिए गए उदाहरण में सेवा के रूप में)

एक स्थानीय ब्रॉडकास्ट मैनेजर का उपयोग करें। अपनी सेवा के क्रिएट में, प्रसारक की स्थापना करें:

 broadcaster = LocalBroadcastManager.getInstance(this); 

जब आप कुछ की UI को सूचित करना चाहते हैं:

 static final public String COPA_RESULT = "com.controlj.copame.backend.COPAService.REQUEST_PROCESSED"; static final public String COPA_MESSAGE = "com.controlj.copame.backend.COPAService.COPA_MSG"; public void sendResult(String message) { Intent intent = new Intent(COPA_RESULT); if(message != null) intent.putExtra(COPA_MESSAGE, message); broadcaster.sendBroadcast(intent); } 

आपकी गतिविधि में:

OnCreate पर एक श्रोता बनाएँ:

 public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); super.setContentView(R.layout.copa); receiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String s = intent.getStringExtra(COPAService.COPA_MESSAGE); // do something here. } }; } 

और इसे स्टार्ट में पंजीकृत करें:

 @Override protected void onStart() { super.onStart(); LocalBroadcastManager.getInstance(this).registerReceiver((receiver), new IntentFilter(COPAService.COPA_RESULT) ); } @Override protected void onStop() { LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver); super.onStop(); } 

मेरे लिए सबसे सरल समाधान एक प्रसारण भेजने के लिए था, उस गतिविधि की शुरुआत में मैंने पंजीकृत किया और इस तरह के प्रसारण को परिभाषित किया (अपडेटयूआईआरइसीवर को एक क्लास इंस्टेंस के रूप में परिभाषित किया गया है):

  IntentFilter filter = new IntentFilter(); filter.addAction("com.hello.action"); updateUIReciver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { //UI update here } }; registerReceiver(updateUIReciver,filter); 

और सेवा से आप इस तरह से इरादा भेजते हैं:

 Intent local = new Intent(); local.setAction("com.hello.action"); this.sendBroadcast(local); 

विनाश पर गतिविधि में पुनर्प्राप्त करने के लिए पंजीकरण रद्द करना मत भूलना:

 unregisterReceiver(updateUIReciver); 

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

मैं ऐसा करने के लिए एक बाध्य सेवा का उपयोग करेगा और मेरी गतिविधि में श्रोता को कार्यान्वित करके इसके साथ संवाद करेगा। इसलिए यदि आपका ऐप मेरे सेवा सेवा प्रबंधक को लागू करता है, तो आप इसे अपनी सेवा में श्रोता के रूप में पंजीकृत कर सकते हैं, अपनी बाध्य सेवा से listener.onUpdateUI को कॉल कर सकते हैं और वहां अपनी यूआई को अपडेट कर सकते हैं!

क्लाईड का समाधान काम करता है, लेकिन यह एक प्रसारण है, जो मुझे पूरा यकीन है कि एक पद्धति सीधे फोन करने से कम कुशल होंगे। मुझे गलत माना जा सकता है, लेकिन मुझे लगता है कि प्रसारण के लिए अंतर-अनुप्रयोग संचार के लिए अधिक मतलब है।

मैं मानता हूं कि आप पहले से ही जानते हैं कि किसी गतिविधि के साथ सेवा कैसे बाँधनी है I मैं इस प्रकार की समस्या को संभालने के लिए नीचे दिए गए कोड की तरह कुछ करता हूं:

 class MyService extends Service { MyFragment mMyFragment = null; MyFragment mMyOtherFragment = null; private void networkLoop() { ... //received new data for list. if(myFragment != null) myFragment.updateList(); } ... //received new data for textView if(myFragment !=null) myFragment.updateText(); ... //received new data for textView if(myOtherFragment !=null) myOtherFragment.updateSomething(); ... } } class MyFragment extends Fragment { public void onResume() { super.onResume() //Assuming your activity bound to your service getActivity().mMyService.mMyFragment=this; } public void onPause() { super.onPause() //Assuming your activity bound to your service getActivity().mMyService.mMyFragment=null; } public void updateList() { runOnUiThread(new Runnable() { public void run() { //Update the list. } }); } public void updateText() { //as above } } class MyOtherFragment extends Fragment { public void onResume() { super.onResume() //Assuming your activity bound to your service getActivity().mMyService.mMyOtherFragment=this; } public void onPause() { super.onPause() //Assuming your activity bound to your service getActivity().mMyService.mMyOtherFragment=null; } public void updateSomething() {//etc... } } 

मैंने धागा सुरक्षा के लिए बिट्स छोड़ा, जो आवश्यक है। सुनिश्चित करें कि लॉक या कुछ ऐसा प्रयोग करें जैसे कि सेवा पर टुकड़े के संदर्भों की जांच और उपयोग या बदलते समय

 Callback from service to activity to update UI. ResultReceiver receiver = new ResultReceiver(new Handler()) { protected void onReceiveResult(int resultCode, Bundle resultData) { //process results or update UI } } Intent instructionServiceIntent = new Intent(context, InstructionService.class); instructionServiceIntent.putExtra("receiver", receiver); context.startService(instructionServiceIntent); 

मेरा समाधान साफ ​​नहीं हो सकता है, लेकिन इसे बिना किसी समस्या के काम करना चाहिए। तर्क केवल एक स्थिर वैरिएबल बनाने के लिए है, जो आपके डेटा को Service पर संग्रहीत करता है और आपकी Activity को आपके Activity पर प्रत्येक दूसरे को अपडेट करता है।

मान लीजिए कि आपके पास आपकी Service पर एक String जिसे आप इसे अपनी Activity पर एक TextView पर भेजना चाहते हैं। इसे ऐसा दिखना चाहिए

सेवा में:

 public class TestService extends Service { public static String myString = ""; // Do some stuff with myString 

आपकी सक्रियता:

 public class TestActivity extends Activity { TextView tv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); tv = new TextView(this); setContentView(tv); update(); Thread t = new Thread() { @Override public void run() { try { while (!isInterrupted()) { Thread.sleep(1000); runOnUiThread(new Runnable() { @Override public void run() { update(); } }); } } catch (InterruptedException ignored) {} } }; t.start(); startService(new Intent(this, TestService.class)); } private void update() { // update your interface here tv.setText(TestService.myString); } }