2014-10-05 8 views
15

पर फ़ंक्शन संदर्भ पास करें I एंड्रॉइड के लिए नया है और वेब विकास के लिए बहुत उपयोग किया जाता है। जावास्क्रिप्ट में जब आप एक अतुल्यकालिक कार्य आप एक तर्क के रूप में एक समारोह पारित (एक कॉलबैक) निष्पादित करना चाहते हैं:एंड्रॉइड: AsyncTask

http.get('www.example.com' , function(response){ 
    //some code to handle response 
}); 

अगर हम एंड्रॉयड के AsyncTask साथ भी ऐसा ही कर सकते हैं मैं सोच रहा था, onPostExecute() विधि करने के लिए एक समारोह संदर्भ पारित , और यह इसे चलाएगा।

कोई सुझाव?

+0

यह नहीं है कि आप इसे कैसे करते हैं^_ ^। आप एसिंक कार्य का उपयोग करके पृष्ठभूमि थ्रेड बनाते हैं और आपका कोड उर्फ ​​httprequest doInBackground() विधि में जाता है और आप इसके लिए रिटर्नटाइप परिभाषित करते हैं। पृष्ठभूमि ऑपरेशन को समाप्त करने के बाद पोस्टस्टेक्स्यूट() को कॉल किया जाता है जिसमें आप प्रतिक्रिया को संभालने के लिए कोड लिखते हैं क्योंकि अब आप दृश्यों को अपडेट कर सकते हैं और सभी। एक प्रगतिशील विधि है जो परिभाषित प्रगति पर पहुंचने पर ट्रिगर होती है। मुझे थोड़ी देर में प्रलेखन लिंक मिलेगा – Rico

+0

http://developer.android.com/reference/android/os/AsyncTask.html – Rico

उत्तर

41

हां जावा में कॉलबैक की अवधारणा भी बहुत अधिक मौजूद है। जावा में आप इस तरह एक कॉलबैक को परिभाषित:

public interface TaskListener { 
    public void onFinished(String result); 
} 

एक अक्सर घोंसला AsyncTask इस तरह अंदर श्रोता परिभाषाएँ इस तरह होगा:

public class ExampleTask extends AsyncTask<Void, Void, String> { 

    public interface TaskListener { 
     public void onFinished(String result); 
    } 

    ... 
} 

और AsyncTask में कॉलबैक का एक पूरा कार्यान्वयन लगेगा इस तरह:

public class ExampleTask extends AsyncTask<Void, Void, String> { 

    public interface TaskListener { 
     public void onFinished(String result); 
    } 

    // This is the reference to the associated listener 
    private final TaskListener taskListener; 

    public ExampleTask(TaskListener listener) { 
     // The listener reference is passed in through the constructor 
     this.taskListener = listener; 
    } 

    @Override 
    protected String doInBackground(Void... params) { 
     return doSomething(); 
    } 

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

     // In onPostExecute we check if the listener is valid 
     if(this.taskListener != null) { 

      // And if it is we call the callback function on it. 
      this.taskListener.onFinished(result); 
     } 
    } 
} 

onPostExecute() जैसे ही पृष्ठभूमि कार्य पूर्ण होने के रूप में कहा जाता है। आप इस तरह पूरी बात का उपयोग कर सकते हैं:

ExampleTask task = new ExampleTask(new ExampleTask.TaskListener() { 
    @Override 
    public void onFinished(String result) { 
     // Do Something after the task has finished 
    } 
}); 

task.execute(); 

या आप इस तरह पूरी तरह से अलग TaskListener परिभाषित कर सकते हैं:

ExampleTask.TaskListener listener = new ExampleTask.TaskListener() { 
    @Override 
    public void onFinished(String result) { 
     // Do Something after the task has finished 
    } 
}; 

ExampleTask task = new ExampleTask(listener);  
task.execute(); 

या आप इस तरह TaskListener उपवर्ग कर सकते हैं:

public class ExampleTaskListener implements TaskListener { 

    @Override 
    public void onFinished(String result) { 

    } 
} 

और फिर इसे इस तरह उपयोग करें:

ExampleTask task = new ExampleTask(new ExampleTaskListener());  
task.execute(); 

आप निश्चित रूप से सिर्फ AsyncTask की onPostExecute() विधि ओवरराइड कर सकते हैं, लेकिन यह सिफारिश की और ज्यादातर मामलों में नहीं है वास्तव में बहुत बुरा व्यवहार। उदाहरण के लिए आप ऐसा कर सकता है:

ExampleTask task = new ExampleTask() { 
    @Override 
    public void onPostExecute(String result) { 
     super.onPostExecute(result); 

     // Your code goes here 
    } 
}; 

यह एक अलग श्रोता इंटरफेस के साथ ऊपर कार्यान्वयन के रूप में बस के रूप में अच्छी तरह से काम करेगा, लेकिन इसके साथ कुछ समस्याएं हैं:

सबसे पहले आप वास्तव में तोड़ सकते हैं ExampleTask सभी एक साथ। यह सब ऊपर super.onPostExecute() कॉल पर आता है। यदि आप डेवलपर के रूप में ऊपर की तरह onPostExecute() ओवरराइड करते हैं और सुपर कॉल को शामिल करना भूल जाते हैं या में मूल onPostExecute() विधि को किसी भी कारण से हटा दें तो उसे अब और नहीं कहा जाएगा। उदाहरण के लिए TaskListener के साथ पूरे श्रोता कार्यान्वयन अचानक काम नहीं करेगा क्योंकि कॉलबैक पर कॉल onPostExecute() में लागू किया गया है। आप TaskListener को अनजाने में या अनजाने में ExampleTask की स्थिति को प्रभावित करके कई अन्य तरीकों से तोड़ सकते हैं, इसलिए यह अब और काम नहीं करेगा।

यदि आप इस तरह की विधि को ओवरराइड करते समय वास्तव में क्या हो रहा है, तो यह और अधिक स्पष्ट हो जाता है कि क्या हो रहा है।onPostExecute() ओवरराइड करके आप ExampleTask का नया उप-वर्ग बना रहे हैं। ऐसा करने के समान ही यह होगा:

public class AnotherExampleTask extends ExampleTask { 

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

     // Your code goes here 
    } 
} 

यह सब सिर्फ अज्ञात वर्ग नामक भाषा सुविधा के पीछे छिपा हुआ है। इस तरह की एक विधि को अचानक ओवरराइड करना इतना साफ और त्वरित नहीं लगता है?

संक्षेप में:

  • इस तरह की एक विधि वास्तव में एक नया उपवर्ग बनाता ओवरराइड करना। आप केवल कॉलबैक नहीं जोड़ रहे हैं, आप संशोधित कर रहे हैं कि यह वर्ग कैसे काम करता है और अनजाने में ओह इतनी सारी चीज़ें तोड़ सकता है।
  • इस तरह की त्रुटियों को डिबग करना ** में केवल दर्द से कहीं अधिक हो सकता है। क्योंकि अचानक ExampleTaskExceptions फेंक सकता है या किसी भी स्पष्ट कारण के लिए अब और काम नहीं कर सकता है, क्योंकि आपने वास्तव में कभी भी अपना कोड संशोधित नहीं किया है।
  • प्रत्येक वर्ग को उन स्थानों पर श्रोता कार्यान्वयन प्रदान करना पड़ता है जहां यह उचित और इरादा है। निश्चित रूप से आप उन्हें बाद में onPostExecute() ओवरराइड करके जोड़ सकते हैं लेकिन यह हमेशा बहुत खतरनाक होता है। यहां तक ​​कि उनकी 13k प्रतिष्ठा के साथ @flup भी super.onPostExecute() को अपने उत्तर में कॉल करने के लिए भूल गया है, कल्पना करें कि कुछ अन्य अनुभवी डेवलपर क्या कर सकते हैं!
  • थोड़ा अबास्ट्रक्शन किसी को चोट नहीं पहुंचाता है। विशिष्ट श्रोताओं को लिखना थोड़ा और कोड हो सकता है, लेकिन यह एक बेहतर समाधान है। कोड क्लीनर, अधिक पठनीय और बहुत अधिक रखरखाव योग्य होगा। onPostExecute() ओवरराइड करने जैसे शॉर्टकट का उपयोग करना अनिवार्य रूप से थोड़ी सी सुविधा के लिए कोड गुणवत्ता को बलिदान देता है। यह कभी भी एक अच्छा विचार नहीं है कि एक इच्छा लंबे समय तक समस्याओं का कारण बन जाएगी।
+0

यह उत्तर सामान्य 'इंटरफ़ेस टास्कलिस्टर ' और 'ऑनफिनिश (टी परिणाम) का उपयोग करके बेहतर किया जा सकता है) ' –

+0

@ क्रिकेट_007 मैं इसे एक सुधार नहीं कहूंगा। प्रत्येक कार्य में अपना स्वयं का कड़ाई से परिभाषित श्रोता होना चाहिए। टाइप एरर को अनदेखा करते समय भी बाकी सब कुछ खराब डिजाइन और कार्यान्वयन के मुद्दों का कारण बनता है। –

+0

हालांकि, इसे केवल 'स्ट्रिंग' प्रतिक्रियाओं तक सीमित करने से अधिक लचीला है।मैंने AsyncTask पर कॉलबैक दृष्टिकोण का उपयोग करके एक प्रश्न का उत्तर दिया है। [उदाहरण के लिए] (http://stackoverflow.com/a/36105515/2308683), आप कहते हैं कि खराब डिजाइन की ओर जाता है? –

2

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

डिनबैकग्राउंड के कार्यान्वयन के साथ AsyncTask के उप-वर्ग के लिए Make an HTTP request with android देखें जो वेब अनुरोध करता है।

यदि आप अलग-अलग कॉलबैक के साथ कई HTTP अनुरोध करना चाहते हैं, तो आप अनुरोध कॉल को ओवरराइड कर सकते हैं और विभिन्न कॉलबैक कार्यान्वयन के साथपोस्टएक्सक्यूट पर लागू कर सकते हैं। आप बंद एक जावास्क्रिप्ट कॉलबैक आमतौर पर उपयोग करता अनुकरण करने के लिए एक अनाम वर्ग का उपयोग कर सकते हैं:

new RequestTask(){ 
    @Override 
    public void onPostExecute(String result) { 
     // Implementation has read only access to 
     // final variables in calling scope. 
    } 
}.execute("http://stackoverflow.com"); 

Xaver पता चलता है, तो आप भी श्रोता के लिए एक पूर्ण विकसित इंटरफ़ेस बना सकते हैं। यह केवल मेरे लिए उपयोगी लगता है यदि आप दो डिफ़ॉल्ट डिफ़ॉल्ट रूप से PostExecute फ़ंक्शंस को कार्यान्वित करना चाहते हैं और किसी विशेष कॉल के लिए इन डिफ़ॉल्ट कार्यान्वयन में से कोई एक चुनना चाहते हैं।

+0

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

+0

@XaverKapeller वास्तव में, सुपर क्लास का 'onPostExecute' कोई काम नहीं करता है और इसे कॉल करना काफी व्यर्थ है। 'OnPostExecute' * कॉलबैक है, कुछ आंतरिक कार्यान्वयन विधि नहीं है जिसे आप चुपके से हुक कर सकते हैं। इसका उद्देश्य कार्य के मूल निर्माता को परिणाम की अधिसूचना है। – flup

+0

वैसे हाँ यह सच है यदि आप एक नया 'AsyncTask' लागू कर रहे हैं, लेकिन यदि आप पहले से ही 'अनुरोध टास्क' जैसे 'AsyncTask' को उपclassed करते हैं, तो आपके उत्तर में' अनुरोध टास्क 'जैसा सुझाव मिलता है कि आप किसी भी कार्यक्षमता को तोड़ सकते हैं जो पहले से ही' RequestTask 'में लागू किया गया था। मेरी पिछली टिप्पणी में मेरा यही मतलब था। –

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