2012-04-01 16 views
129

पर कॉलबैक भेज रहा है मेरे पास निम्नलिखित एसिंक्टास्क क्लास है जो गतिविधि के अंदर नहीं है। गतिविधि में मैं asynctask शुरू कर रहा हूं, और मैं asynctask को अपनी गतिविधि पर वापस कॉलबैक की रिपोर्ट करना चाहता हूं। क्या यह संभव है? या एसिंक्टास्क गतिविधि के समान कक्षा फ़ाइल में होना चाहिए?एंड्रॉइड एसिंक्टास्क ui

protected void onProgressUpdate(Integer... values) 
{ 
    super.onProgressUpdate(values); 
    caller.sometextfield.setText("bla"); 
} 

ऐसा कुछ?

उत्तर

365

आप एक interface बनाने के लिए, AsyncTask को इसे पारित (निर्माता में) कर सकते हैं, और फिर onPostExecute()

में विधि कॉल उदाहरण के लिए:

आपका इंटरफ़ेस:

public interface OnTaskCompleted{ 
    void onTaskCompleted(); 
} 

आपका गतिविधि:

public class YourActivity implements OnTaskCompleted{ 
    // your Activity 
} 

एन घ अपने AsyncTask:

public class YourTask extends AsyncTask<Object,Object,Object>{ //change Object to required type 
    private OnTaskCompleted listener; 

    public YourTask(OnTaskCompleted listener){ 
     this.listener=listener; 
    } 

    // required methods 

    protected void onPostExecute(Object o){ 
     // your stuff 
     listener.onTaskCompleted(); 
    } 
} 

संपादित

के बाद से इस सवाल का जवाब काफी लोकप्रिय हो गया है, मैं कुछ बातें जोड़ना चाहते हैं।

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

  • मेमोरी लीक की संभावना। यदि आप अपने Activity का संदर्भ रखते हैं, तो उपयोगकर्ता स्क्रीन को छोड़ने के बाद भी स्मृति में रहेगा (या डिवाइस को घुमाएगा)।
  • AsyncTaskActivity पर परिणाम नहीं दे रहा है यदि Activity पहले से ही नष्ट हो गया था। आपको इन सभी चीजों को प्रबंधित करने के लिए अतिरिक्त कोड जोड़ना होगा या आप दो बार संचालन करेंगे।
  • जटिल कोड जो Activity

में सब कुछ करता है जब आपको लगे कि आप Android के साथ आगे बढ़ने के लिए, this article पर एक नज़र डालें, जो मुझे लगता है कि पर्याप्त परिपक्व, अपने Android ऐप्स के विकास के लिए जाने के लिए एक बेहतर तरीका है एसिंक्रोनस ऑपरेशंस के साथ।

+0

क्या एसिन्टास्क क्लास को मेनिफेस्ट फ़ाइल में लिखा जाना चाहिए? –

+1

@AsafNevo नहीं, यह –

+0

@Dmitry नहीं होना चाहिए, श्रोता के अलावा अन्य क्या श्रोता हमारे पास हो सकता है? PreExecute पर क्या है? – rxlky

6

उपर्युक्त उत्तरों को पूरा करने में, आप अपने प्रत्येक एसिंक कॉल के लिए अपने फ़ॉलबैक को भी कस्टमाइज़ कर सकते हैं, ताकि सामान्य ASYNC विधि में प्रत्येक कॉल आपके द्वारा रखे गए टास्कडोन सामग्री के आधार पर अलग-अलग डेटा को पॉप्युलेट कर सके।

Main.FragmentCallback FC= new Main.FragmentCallback(){ 
      @Override 
      public void onTaskDone(String results) { 

       localText.setText(results); //example TextView 
      } 
     }; 

new API_CALL(this.getApplicationContext(), "GET",FC).execute("&Books=" + Main.Books + "&args=" + profile_id); 

याद दिलाएं: मैं, मुख्य गतिविधि thats जहां "मुख्य" आता है पर इंटरफेस का इस्तेमाल किया इस तरह:

public interface FragmentCallback { 
    public void onTaskDone(String results); 


} 

मेरे एपीआई पोस्ट को इस प्रकार दिखता निष्पादित करें:

@Override 
    protected void onPostExecute(String results) { 

     Log.i("TASK Result", results); 
     mFragmentCallback.onTaskDone(results); 

    } 

एपीआई कन्स्ट्रक्टर इस तरह दिखता है:

class API_CALL extends AsyncTask<String,Void,String> { 

    private Main.FragmentCallback mFragmentCallback; 
    private Context act; 
    private String method; 


    public API_CALL(Context ctx, String api_method,Main.FragmentCallback fragmentCallback) { 
     act=ctx; 
     method=api_method; 
     mFragmentCallback = fragmentCallback; 


    } 
+3

आइडिया अच्छा है, लेकिन 'Main.FragmentCallback' की अनाम कार्यान्वयन के साथ सावधान रहना होगा" यह सब सामान के प्रबंधन के लिए अतिरिक्त कोड जोड़ने "- यह' रिसाव हो सकता है Activity' का उपयोग कर 'WeakReference' पर विचार करें। करने के लिए यह। –

+0

वास्तव में क्यों इस प्रश्न पूछा गया था ऊपर जवाब में से बॉट गतिविधि रिसाव अगर गतिविधि जबकि Asynctask अपनी गुमनाम आंतरिक वर्ग जो अपनी गतिविधि एक अंतर्निहित संदर्भ – user1530779

37

मुझे लगा कि नीचे का दृष्टिकोण बहुत आसान है।

मैं समानांतर अनुरोध

public class MyAsyncTask extends AsyncTask<Object, Object, Object> { 

    public AsyncResponse delegate = null;//Call back interface 

    public MyAsyncTask(AsyncResponse asyncResponse) { 
     delegate = asyncResponse;//Assigning call back interfacethrough constructor 
    } 

    @Override 
    protected Object doInBackground(Object... params) { 

    //My Background tasks are written here 

     return {resutl Object} 

    } 

    @Override 
    protected void onPostExecute(Object result) { 
     delegate.processFinish(result); 
    } 

} 

फिर अतुल्यकालिक कार्य जब गतिविधि कक्षा में एक बटन क्लिक कहा जाता है के सभी प्रकार के लिए जवाब कॉलबैक

public interface AsyncResponse { 
    void processFinish(Object output); 
} 

फिर बनाया अतुल्यकालिक कार्य के लिए एक इंटरफेस घोषित किया है।

public class MainActivity extends Activity { 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 

     Button mbtnPress = (Button) findViewById(R.id.btnPress); 

     mbtnPress.setOnClickListener(new View.OnClickListener() { 

      @Override 
      public void onClick(View v) { 

       MyAsyncTask asyncTask =new MyAsyncTask(new AsyncResponse() { 

        @Override 
        public void processFinish(Object output) { 
         Log.d("Response From Asynchronous task:", (String) output);   
         mbtnPress.setText((String) output); 
        } 
       }); 
       asyncTask.execute(new Object[] { "Youe request to aynchronous task class is giving here.." }); 

      } 
     }); 
    } 
} 

धन्यवाद

+0

फिर एक स्मृति रिसाव स्थिति – user1530779

+0

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

+0

आप के रूप में ही .. यह मेरे जैसे शुरुआती] के लिए सबसे अच्छा जवाब है – 707

2

मैं फिर कहता हूँ कि क्या अन्य लोगों ने कहा, लेकिन सिर्फ यह सरल बनाने के लिए प्रयास किया जाएगा ...

सबसे पहले, बस इंटरफ़ेस वर्ग

public interface PostTaskListener<K> { 
    // K is the type of the result object of the async task 
    void onPostTask(K result); 
} 

दूसरा बनाने के , AsyncTask (जो आपकी गतिविधि या खंड का एक आंतरिक स्थैतिक वर्ग हो सकता है) बनाएं जो एक ठोस वर्ग सहित इंटरफ़ेस का उपयोग करता है। उदाहरण में, पोस्टटास्कलिस्टर को स्ट्रिंग के साथ पैरामीटर किया गया है, जिसका अर्थ है कि यह एसिंक कार्य के परिणामस्वरूप स्ट्रिंग क्लास की अपेक्षा करता है।

public static class LoadData extends AsyncTask<Void, Void, String> { 

    private PostTaskListener<String> postTaskListener; 

    protected LoadData(PostTaskListener<String> postTaskListener){ 
     this.postTaskListener = postTaskListener; 
    } 

    @Override 
    protected void onPostExecute(String result) { 
     super.onPostExecute(result); 

     if (result != null && postTaskListener != null) 
      postTaskListener.onPostTask(result); 
    } 
} 

अंत में, वह हिस्सा जहां आप अपना तर्क जोड़ते हैं। अपनी गतिविधि/खंड में, PostTaskListener बनाएं और इसे async कार्य में पास करें। यहां एक उदाहरण दिया गया है:

... 
PostTaskListener<String> postTaskListener = new PostTaskListener<String>() { 
    @Override 
    public void onPostTask(String result) { 
     //Your post execution task code 
    } 
} 

// Create the async task and pass it the post task listener. 
new LoadData(postTaskListener); 

हो गया!