2012-02-25 13 views
7

मेरा मुद्दा इस Instance variable of Activity not being set in onPostExecute of AsyncTask or how to return data from AsyncTask to main UI thread जैसा ही है, लेकिन मैं डेटा को उसी कॉलिंग गतिविधि पर वापस भेजना चाहता हूं। शुरू नहीं होता है इरादों के लिए सक्रियता हमेशा गतिविधि को पुनरारंभ करेंमैं AsyncTask मेंPostExecute से डेटा वापस कैसे भेजूं?

उत्तर

13

पर उपयोग कर सकते हैं आप दृश्य को अपडेट करना चाहते हैं विकल्प पर श्रोताओं है, जहां आप एक इंटरफेस बनाने के उपयोग करने के लिए है कि अपनी गतिविधि implents, कुछ की तरह:

public interface AsyncListener { 
    public void doStuff(MyObject obj); 
} 

इस तरह,

protected void onPostExecute(MyObject obj) { 
    asyncListener.doStuff(obj); 
} 
6

यह आपकी कक्षा संरचना पर निर्भर करता है, लेकिन यदि आपकी AsyncTask आपकी गतिविधि के भीतर एक कक्षा है तो आप उस गतिविधि के तरीकों का संदर्भ दे सकते हैं। आप क्या करेंगे क्या आपके onPostExecute विधि अपनी गतिविधि के एक समारोह है कि कुछ डेटा है कि गतिविधि जहां फिर इसे उपयोग कर सकते हैं करने के लिए AsyncTask में प्राप्त की गई थी गुजरता फोन में है ..

कोड इस

कैसा लगेगा
class YourActivity extends Activity { 
    private static final int DIALOG_LOADING = 1; 

    public void onCreate(Bundle savedState) { 
    setContentView(R.layout.yourlayout); 
    showDialog(DIALOG_LOADING);  
    new LongRunningTask1().execute(1,2,3); 

    } 

    protected Dialog onCreateDialog(int dialogId) { 
    switch(dialogId) { 
     case DIALOG_LOADING: 
      ProgressDialog pDialog = new ProgressDialog(this); 
      pDialog.setTitle("Loading Data"); 
      pDialog.setMessage("Loading Data, please wait..."); 
      return pDialog; 
     default: 
      return super.onCreateDialog(dialogId); 
     }  
    } 

    private void onBackgroundTaskDataObtained(List<String> results) { 
     dismissDialog(DIALOG_LOADING); 
    //do stuff with the results here.. 
    } 

    private class LongRunningTask extends AsyncTask<Long, Integer, List<String>> { 
     @Override 
     protected void onPreExecute() { 
      //do pre execute stuff 
     } 

     @Override 
     protected List<String> doInBackground(Long... params) { 
      List<String> myData = new ArrayList<String>(); 
      for (int i = 0; i < params.length; i++) { 
       try { 
        Thread.sleep(params[i] * 1000); 
        myData.add("Some Data" + i); 
       } catch(InterruptedException ex) { 
       }     
      } 
      return myData; 
     } 

     @Override 
     protected void onPostExecute(List<String> result) { 
      YourActivity.this.onBackgroundTaskDataObtained(result); 
     }  
    } 

} 

तो सामान्य प्रवाह इस तरह है, वर्तमान पृष्ठ का दृश्य सेट करें, और उसके बाद प्रगति संवाद दिखाएं। उसके बाद एसिंक कार्य शुरू करें (या जब भी, यह वास्तव में कोई फर्क नहीं पड़ता)।

आपके एसिंक कार्य पूरा होने के बाद, गतिविधि का एक फ़ंक्शन कॉल करें और इसे डेटा पास करें। एसिंक कार्य के भीतर साझा डेटा का उपयोग न करें या आप थ्रेडिंग के साथ समस्याओं का जोखिम उठाएं .. इसके बजाय एक बार जब आप इसे पूरा कर लें तो इसे गतिविधि में पास कर दें। उत्तरोत्तर, जबकि काम कर रही आप onProgressUpdate

+0

अपने जवाब के लिए धन्यवाद: अगर आप AsyncTask उपवर्गीकरण कर रहे हैं, यह onPostExecute() में इस श्रोता जोड़ना चाहते हैं तो आसान है, आप की तरह कुछ कर सकता है। मैं AsyncTask के उप प्रशंसक के रूप में उपयोग करने का प्रशंसक नहीं हूं। मुझे लगता है कि आप घटनाओं का उपयोग करने में सक्षम होना चाहिए। मुझे लगता है कि उत्तर इरादों का उपयोग कर रहा है लेकिन मैं केवल अपनी गतिविधि का एक नया उदाहरण तैयार करूंगा जो मैं नहीं चाहता हूं। – skinnybrit51

+0

आप आसानी से अपने AsyncTask को अपनी कक्षा में उपयोग कर सकते हैं, लेकिन यह केवल तभी उपयोगी होता है जब आप एक ही तर्क को कई अलग-अलग गतिविधियों से उपयोग कर रहे हों .. इस मामले में आप या तो कर सकते हैं: 1. एक सामान्य बेस क्लास का उपयोग करें (गतिविधि नहीं बल्कि कुछ विस्तार गतिविधि) और फिर आपके पास एक सामान्य विधि होगी जिसे एसिंक कार्य से बुलाया जा सकता है। या बेहतर अभी तक दोनों एक आम इंटरफ़ेस को कार्यान्वित करते हैं जिसमें कॉलबैक जैसा मैंने वर्णन किया है। AsyncTask के कन्स्ट्रक्टर में गतिविधि का संदर्भ पास करें और सुनिश्चित करें कि asyncTask में एक कन्स्ट्रक्टर है जो इंटरफ़ेस प्रकार का पैरामीटर लेता है। –

+0

आपका आखिरी विकल्प AsyncTask को पूरी तरह से मिटाना है और इसे एक ऐसी सेवा में डालना है जिसे आपको पृष्ठभूमि गतिविधि करने के लिए एक नया धागा बनाने की आवश्यकता है (क्योंकि सेवाओं को डिफ़ॉल्ट रूप से अपने धागे में नहीं चलाया जाएगा)। ऐसा करने का एक आसान तरीका एक IntentService बनाना है जो आपके लिए एक नया धागा बनाता है। –

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