2012-06-20 15 views
221

एंड्रॉइड सेवा में मैंने कुछ पृष्ठभूमि कार्य करने के लिए थ्रेड बनाए हैं।किसी अन्य धागे से मुख्य धागे में कोड चलाना

मेरे पास ऐसी स्थिति है जहां थ्रेड को मुख्य थ्रेड के संदेश कतार पर कुछ कार्य पोस्ट करने की आवश्यकता होती है, उदाहरण के लिए Runnable

क्या मुख्य धागे के Handler और Message/Runnable को मेरे अन्य धागे से पोस्ट करने का कोई तरीका है?

धन्यवाद,

+2

आप कस्टम प्रसारण रिसीवर का उपयोग कर सकते हैं .... यहाँ मेरा उत्तर की कोशिश, [इनर प्रसारण रिसीवर] [1] [1]: http://stackoverflow.com/a/22541324/1881527 –

+0

कई तरीके हैं। डेविड के जवाब और डीजेकी की टिप्पणी के जवाब में, (3) आप ब्रॉडकास्ट रिसीवर का उपयोग कर सकते हैं, या (4) सेवा शुरू करने के लिए इस्तेमाल किए गए इरादे के अतिरिक्त हैंडलर को पास कर सकते हैं, और उसके बाद getIntent का उपयोग करके मुख्य थ्रेड के हैंडलर सेवा के अंदर पुनर्प्राप्त कर सकते हैं () .getExtras()। –

उत्तर

475

नोट: इस उत्तर में जी है बहुत ध्यान दिया, कि मुझे इसे अद्यतन करने की जरूरत है। चूंकि मूल उत्तर पोस्ट किया गया था, इसलिए @dzeikei की टिप्पणी को मूल उत्तर के रूप में लगभग उतना ही ध्यान मिला है। (

सुनिश्चित करें कि आपके पृष्ठभूमि कार्यकर्ता धागे एक संदर्भ वस्तु की एक्सेस है ऐप्लिकेशन संदर्भ हो सकता है:

1. अपनी पृष्ठभूमि धागा एक Context वस्तु के लिए एक संदर्भ है, तो: तो यहाँ 2 संभव समाधान हैं या सेवा संदर्भ)। तो बस पृष्ठभूमि कार्यकर्ता सूत्र में ऐसा करते हैं: यदि आपका पृष्ठभूमि धागा नहीं है (या जरूरत)

// Get a handler that can be used to post to the main thread 
Handler mainHandler = new Handler(context.getMainLooper()); 

Runnable myRunnable = new Runnable() { 
    @Override 
    public void run() {....} // This is your code 
}; 
mainHandler.post(myRunnable); 

2. एक Context वस्तु

(@dzeikei ने सुझाव दिया):

// Get a handler that can be used to post to the main thread 
Handler mainHandler = new Handler(Looper.getMainLooper()); 

Runnable myRunnable = new Runnable() { 
    @Override 
    public void run() {....} // This is your code 
}; 
mainHandler.post(myRunnable); 
+0

धन्यवाद डेविड ने मेरे लिए काम किया, एक और बात अगर आप मेरी मदद कर सकते हैं, अगर मैं हैंडलर का विस्तार करता हूं और इम्प्लोर मैसेज() क्या यह मुख्य धागे को अपने संदेशों को संभालने से रोक देगा? यह केवल संक्षेप में एक सवाल है .. – Ahmed

+2

नहीं। यदि आप 'हैंडलर' (या 'हैंडलर। कॉलबैक' इंटरफ़ेस का उपयोग करते हैं) को उपclass करते हैं तो आपकी 'हैंडल मैसेज()' विधि केवल आपके हैंडलर का उपयोग करके पोस्ट किए गए संदेशों के लिए बुलाया जाएगा। मुख्य धागा संदेशों को पोस्ट/संसाधित करने के लिए एक अलग हैंडलर का उपयोग कर रहा है, इसलिए कोई संघर्ष नहीं है। –

+0

धन्यवाद डेविड, आपने मेरा भ्रम हल किया :) – Ahmed

4

एक विधि मैं के बारे में सोच सकते हैं यह है:

1) सेवा करने के लिए यूआई बाँध दें।
2) कि पंजीकृत करता Binder द्वारा नीचे एक तरह एक विधि का पर्दाफाश अपने Handler:

public void registerHandler(Handler handler) { 
    mHandler = handler; 
} 

3) यूआई धागा में, सेवा के लिए बाध्य करने के बाद उपरोक्त विधि फोन:

mBinder.registerHandler(new Handler()); 

4) अपने कार्य को पोस्ट करने के लिए सेवा के धागे में हैंडलर का उपयोग करें:

mHandler.post(runnable); 
116

नीचे एक टिप्पणीकर्ता सही ढंग से इंगित करता है, यह सेवाओं के लिए एक सामान्य समाधान नहीं है, केवल आपकी गतिविधि से शुरू किए गए धागे के लिए (एक सेवा ऐसी धागा हो सकती है, लेकिन उन सभी में से नहीं)। सेवा-गतिविधि संचार के जटिल विषय पर आधिकारिक दस्तावेज़ के पूरे सेवाएं अनुभाग पढ़ें - यह जटिल है, इसलिए यह मूल बातें समझने के लिए भुगतान करने होंगे: http://developer.android.com/guide/components/services.html#Notifications

विधि नीचे simpliest मामलों में काम कर सकते हैं।

यदि मैं आपको सही ढंग से समझता हूं तो आपको एप्लिकेशन के जीयूआई थ्रेड में निष्पादित करने के लिए कुछ कोड की आवश्यकता है ("मुख्य" थ्रेड नामक किसी भी चीज़ के बारे में नहीं सोच सकता)। इसके लिए Activity पर एक विधि है:

someActivity.runOnUiThread(new Runnable() { 
     @Override 
     public void run() { 
      //Your code to run in GUI thread here 
     }//public void run() { 
}); 

डॉक्टर: http://developer.android.com/reference/android/app/Activity.html#runOnUiThread%28java.lang.Runnable%29

आशा यह आपके लिए क्या देख रहे है।

+13

ओपी का कहना है कि वह 'सेवा' में धागे चला रहा है। आप 'सेवा' में 'runOnUiThread() 'का उपयोग नहीं कर सकते हैं। यह जवाब भ्रामक है और पूछे जाने वाले प्रश्न को संबोधित नहीं करता है। –

24

यदि आप थ्रेड में कोड चलाते हैं, उदा। कुछ कार्रवाई में देरी करें, तो आपको संदर्भ से runOnUiThread का आह्वान करने की आवश्यकता है। उदाहरण के लिए, यदि आपका कोड MainActivity वर्ग के अंदर है तो इस का उपयोग करें:

MainActivity.this.runOnUiThread(new Runnable() { 
    @Override 
    public void run() { 
     myAction(); 
    } 
}); 

अपने विधि या तो मुख्य (यूआई धागा) से या अन्य धागे से लागू किया जा सकता है, तो आप की तरह एक जांच की जरूरत है:

public void myMethod() { 
    if(Looper.myLooper() == Looper.getMainLooper()) { 
     myAction(); 
    } 
    else { 

} 
+7

ओपी का कहना है कि वह 'सेवा' में धागे चला रहा है। आप 'सेवा' में 'runOnUiThread() 'का उपयोग नहीं कर सकते हैं। –

+0

@ डेविड वासर क्या यह कहीं भी दस्तावेज है? विधि दस्तावेज़ इस बारे में कुछ भी उल्लेख नहीं करते हैं। http://developer.android.com/reference/android/app/Activity.html#runOnUiThread%28java.lang.Runnable%29 –

+0

@ ग्रेग्राउन जैसा कि आपने 'गतिविधि' दस्तावेज़ के लिंक से संकेत दिया है, 'runOnUiThread () 'गतिविधि 'की एक विधि है। यह 'सेवा' की विधि नहीं है, इसलिए आप इसका उपयोग नहीं कर सकते हैं। उससे स्पष्ट क्या हो सकता है? –

27

यदि आपके पास संदर्भ तक पहुंच नहीं है, तो एक और आसान तरीका है।

1)। मुख्य लूपर से हैंडलर बनाएं:

Handler uiHandler = new Handler(Looper.getMainLooper()); 

2)। एक रननेबल इंटरफ़ेस लागू करें:

Runnable runnable = new Runnable() { // your code here } 

3)। uiHandler करने के लिए अपने Runnable पोस्ट:

uiHandler.post(runnable); 

है यही कारण है कि सभी ;-) धागे के साथ मज़े, लेकिन भूल नहीं है उन्हें सिंक्रनाइज़ करने के लिए।

2

HandlerThread एंड्रॉइड में सामान्य जावा थ्रेड के लिए बेहतर विकल्प है।

  1. एक HandlerThread बनाएँ और शुरू यह
  2. HandlerThread से Looper के साथ एक Handler बनाएँ: requestHandler
  3. postHandlerThread

      से पर यूआई थ्रेड साथ requestHandler

    संचार एक Runnable कार्य

  4. मुख्य थ्रेड के लिए Looper के साथ एक Handler बनाएँ: responseHandler और handleMessage विधि
  5. ओवरराइड अंदर (इस मामले में HandlerThread) अन्य थ्रेड के Runnable कार्य, responseHandler में handleMessage के इस sendMessage परिणाम मंगलाचरण sendMessage
  6. पर responseHandler कहते हैं। Message और यह प्रक्रिया से
  7. गुण प्राप्त करें, अद्यतन यूआई

उदाहरण: अद्यतन TextView डेटा एक वेब सेवा से प्राप्त के साथ। चूंकि गैर-यूआई थ्रेड पर वेब सेवा लागू की जानी चाहिए, नेटवर्क ऑपरेशन के लिए HandlerThread बनाया गया है।एक बार जब आप वेब सेवा से सामग्री प्राप्त कर लेते हैं, तो अपने मुख्य थ्रेड (यूआई थ्रेड) हैंडलर को संदेश भेजें और Handler संदेश को संभालेंगे और यूआई अपडेट करेगा।

नमूना कोड:

HandlerThread handlerThread = new HandlerThread("NetworkOperation"); 
handlerThread.start(); 
Handler requestHandler = new Handler(handlerThread.getLooper()); 

final Handler responseHandler = new Handler(Looper.getMainLooper()) { 
    @Override 
    public void handleMessage(Message msg) { 
     txtView.setText((String) msg.obj); 
    } 
}; 

Runnable myRunnable = new Runnable() { 
    @Override 
    public void run() { 
     try { 
      Log.d("Runnable", "Before IO call"); 
      URL page = new URL("http://www.your_web_site.com/fetchData.jsp"); 
      StringBuffer text = new StringBuffer(); 
      HttpURLConnection conn = (HttpURLConnection) page.openConnection(); 
      conn.connect(); 
      InputStreamReader in = new InputStreamReader((InputStream) conn.getContent()); 
      BufferedReader buff = new BufferedReader(in); 
      String line; 
      while ((line = buff.readLine()) != null) { 
       text.append(line + "\n"); 
      } 
      Log.d("Runnable", "After IO call:"+ text.toString()); 
      Message msg = new Message(); 
      msg.obj = text.toString(); 
      responseHandler.sendMessage(msg); 


     } catch (Exception err) { 
      err.printStackTrace(); 
     } 
    } 
}; 
requestHandler.post(myRunnable); 

उपयोगी लेख:

handlerthreads-and-why-you-should-be-using-them-in-your-android-apps

android-looper-handler-handlerthread-i

0

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

AsyncTask.execute(new Runnable() { 
      @Override 
      public void run() { 

      //code you want to run on the background 
      someCode(); 

      //the code you want to run on main thread 
MainActivity.this.runOnUiThread(new Runnable() { 

        public void run() { 

/*the code you want to run after the background operation otherwise they will executed earlier and give you an error*/ 
         executeAfterOperation(); 

        } 
       }); 
      } 
     }); 
एक सेवा

के मामले में

OnCreate

handler = new Handler(); 

में कोई हैंडलर बनाने तो यह

private void runOnUiThread(Runnable runnable) { 
     handler.post(runnable); 
    } 
+0

इस कोड स्निपेट के लिए धन्यवाद, जो कुछ सीमित, तत्काल सहायता प्रदान कर सकता है। ए [उचित स्पष्टीकरण अपने दीर्घकालिक मूल्य में काफी सुधार करेगा] (// meta.stackexchange.com/q/114762/350567) दिखाकर * क्यों * यह समस्या का एक अच्छा समाधान है, और भविष्य के लिए इसे और अधिक उपयोगी बना देगा अन्य, समान प्रश्नों के साथ पाठक। आपके द्वारा किए गए अनुमानों सहित कुछ स्पष्टीकरण जोड़ने के लिए कृपया अपना उत्तर संपादित करें। – iBug

4

एक गाढ़ा कोड ब्लॉक इस प्रकार है जैसे कि यह का उपयोग करें:

new Handler(Looper.getMainLooper()).post(new Runnable() { 
     @Override 
     public void run() { 
      // things to do on the main thread 
     } 
    }); 

इसमें गतिविधि संदर्भ या अनुप्रयोग संदर्भ को पारित करने में शामिल नहीं है।

 संबंधित मुद्दे

  • कोई संबंधित समस्या नहीं^_^