2012-08-28 24 views
27

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

चूंकि ASyncTasks दोनों स्वतंत्र हैं, इसलिए दूसरा इंतजार करने के लिए बहुत बेवकूफ है। यह अधिक तार्किक asynctasks अलग वर्गों के विभिन्न धागे का उपयोग होगा, क्या मैं गलत हूँ?

ASyncTask दस्तावेज़ पढ़ना। executeOnExecutor() का उपयोग करने के बारे में बात करते हैं, लेकिन मैं 11 से कम एपीआई स्तर में इसे कैसे हल कर सकता हूं?

यहाँ एक छोटा सा उदाहरण है कि "समस्या"

 new Task1().execute(); 
     new Task2().execute(); 
साथ

reproduces चला जाता है

public class Task1 extends AsyncTask<Void, Void, Void> { 

    @Override 
    protected Void doInBackground(Void... params) { 
     GLog.e("doInBackground start 1"); 
     SystemClock.sleep(9000); 
     GLog.e("doInBackground end 1"); 
     return null; 
    } 

    @Override 
    protected void onPreExecute() { 
     GLog.e("onPreExecute 1"); 
     super.onPreExecute(); 
    } 

    @Override 
    protected void onPostExecute(Void result) { 
     GLog.e("onPostExecute 1"); 
     super.onPostExecute(result); 
    } 

} 

public class Task2 extends AsyncTask<Void, Void, Void> { 

    @Override 
    protected void onPreExecute() { 
     GLog.e("onPreExecute 2"); 
     super.onPreExecute(); 
    } 

    @Override 
    protected Void doInBackground(Void... params) { 
     GLog.e("doInBackground start 2"); 
     SystemClock.sleep(9000); 
     GLog.e("doInBackground end 2"); 
     return null; 
    } 

    @Override 
    protected void onPostExecute(Void result) { 
     GLog.e("onPostExecute 2"); 
     super.onPostExecute(result); 
    } 

} 
+0

यूआई को अपडेट करने के लिए आपके पास AsyncTask क्यों है? आपको आईआई थ्रेड पर सिंक्रनाइज़ करने की ज़रूरत है। क्या आपका UI AsyncTask पृष्ठभूमि थ्रेड पर कुछ और करता है? –

+0

मैं इसका उपयोग समाचार के साथ एक सूचीदृश्य दिखाने के लिए उदाहरण के लिए करता हूं। OnPreExecute में मैं लोडिंग() UI दिखाता हूं, पृष्ठभूमि में इंटरनेट से समाचार पुनर्प्राप्त करता है और onPostExecute एडाप्टर को सूचीदृश्य में असाइन करता है। क्या यह दृष्टिकोण गलत है? – Addev

+0

@Addev: आप पहले 'onPostExecute (...)' विधि में दूसरी 'AsyncTask' क्यों शुरू नहीं करते हैं? यदि आपको जो चाहिए वह यह है कि एक 'AsyncTask' दूसरे के परिणाम पर निर्भर करता है तो आपके पास प्रभावी रूप से एक तुल्यकालिक आवश्यकता होती है और आपको समानांतर में दो एसिंक्रोनस ऑपरेशंस नहीं चलाना चाहिए। – Squonk

उत्तर

46

यह मैं अपने कोड में इस संभाल है:

if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { 
    new MyAsyncTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); 
} else { 
    new MyAsyncTask().execute(); 
} 

और MyAsyncTask की जगह आपके Task1 और Task2 क्रमशः। मूल रूप से AsyncTask में परिवर्तन हनीकॉम में दिखाई देता है (एंड्रॉइड एसडीके दस्तावेज़ here "निष्पादन आदेश" खंड में देखें), इससे पहले, आप इसे सामान्य रूप से लॉन्च करते हैं, एचसी और ऊपर के लिए, executeOnExecutor() का उपयोग करें यदि आपको नया व्यवहार पसंद नहीं है (कोई नहीं करता है, मुझे लगता है कि)

7

एक से थोड़ा अधिक सामान्य तरीका यह है तो तरह एक उपयोगिता कक्षा में दो सहायक तरीकों डाल करने के लिए है:

class Utils { 

    @SuppressLint("NewApi") 
    public static <P, T extends AsyncTask<P, ?, ?>> void execute(T task, P... params) { 
     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { 
      task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params); 
     } else { 
      task.execute(params); 
     } 
    } 
} 

तो फिर तुम Utils.execute(mytask) या Utils.execute(mytask, params) के साथ कार्य निष्पादित कर सकते हैं और यह ध्यान रखना होगा समानांतर में उन्हें निष्पादित करना।

+0

धन्यवाद। वंशावली के लिए नोट, 'AsyncTask.execute() 'को ओवरराइड करने का प्रयास न करें - आप नहीं कर सकते; यह 'अंतिम' है। – TalkLittle

+0

इसके अलावा पहली विधि अनावश्यक है और वास्तव में अप्रत्याशित व्यवहार का कारण बन सकती है ('पैराम' खाली सरणी के बजाय 'शून्य' हो सकती है)। इसे पूर्व-हनीकॉम डिवाइस पर संकलित/चलाता है। – TalkLittle

+0

यह अनावश्यक नहीं है, यह टाइपिंग बचाता है :) –

0

समस्या यह है कि प्रत्येक AsyncTask उसी थ्रेडपूलएक्सएटर में चलाया जाता है जिसे एपीआई में कोड किया जाता है। यह ThreadPoolExecutor आपके एंड्रॉइड संस्करण के आधार पर वर्कर थ्रेड की एक अलग संख्या बना सकता है। मुझे संख्या संस्करण याद नहीं है लेकिन विचार यह है कि पुराने एंड्रॉइड संस्करणों में यह 1 वर्कर थ्रेड था। फिर इसे बाद के संस्करणों में 5 तक अपडेट किया गया था। और हाल ही में 1 फिर से वापस ले जाया गया। यही कारण है कि आपके AsyncTasks अवरुद्ध हैं। वे सभी एक ही वर्कर थ्रेड पर चलते हैं और इस प्रकार वे अनुक्रमिक रूप से निष्पादित होते हैं। सही समांतर निष्पादन प्राप्त करने के लिए THREAD_POOL_EXECUTOR के साथ executeOnExecutor का उपयोग करने का प्रयास करें। हालांकि आप इसका उपयोग एपीआई 11 के बाद ही कर सकते हैं।

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

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