समस्या पहले:एंड्रॉइड - थ्रेड पूल रणनीति और क्या इसे लोड करने के लिए लोडर का उपयोग किया जा सकता है?
- मैं एक स्वनिर्धारित
FragmentStatePagerAdapter
के भीतर कईFragmentLists
का उपयोग करता है आवेदन पर काम कर रहा हूँ। हो सकता है, संभावित रूप से पर्याप्त संख्या में ऐसे टुकड़े 20 और 40 के बीच कहते हैं। - प्रत्येक खंड एक सूची है जिसमें प्रत्येक आइटम में टेक्स्ट या छवि हो सकती है।
- छवियों एसडी वेब से एसिंक्रोनस रूप से अपलोड करने की और अस्थायी मेमोरी कैश करने के लिए कैश की गई है और यह भी जरूरत है, यदि उपलब्ध
- टुकड़ा स्क्रीन किसी भी अपलोड और वर्तमान गतिविधि को रद्द कर दिया जाना चाहिए बंद हो जाता है जब (नहीं रोका गया)
मेरा पहला कार्यान्वयन Google से image loader code को अच्छी तरह से जाना जाता है। उस कोड के साथ मेरी समस्या यह है कि यह मूल रूप से AsyncTask
प्रति छवि का एक उदाहरण बनाता है। जो मेरे मामले में ऐप को वास्तविक तेज़ मारता है।
चूंकि मैं v4 संगतता पैकेज का उपयोग कर रहा हूं, मैंने सोचा था कि AsyncTaskLoader
तक विस्तारित कस्टम लोडर का उपयोग करने से मुझे आंतरिक रूप से थ्रेड पूल लागू होता है। हालांकि मेरे अप्रिय आश्चर्य के लिए यदि मैं इस कोड को कई बार निम्नलिखित निष्पादन निष्पादित करता हूं तो पिछले को बाधित कर देगा। मैं अपने ListView#getView
विधि में इस राशि कहते हैं:
getSupportLoaderManager().restartLoader(0, args, listener);
इस विधि प्रत्येक सूची आइटम उस दृश्य में आता है के लिए पाश में मार डाला गया है। और जैसा कि मैंने कहा - प्रत्येक निम्नलिखित आमंत्रण पिछले एक को समाप्त कर देगा। या कम से कम है कि क्या LogCat
11-03 13:33:34.910: V/LoaderManager(14313): restartLoader in LoaderManager: args=Bundle[{URL=http://blah-blah/pm.png}]
11-03 13:33:34.920: V/LoaderManager(14313): Removing pending loader: LoaderInfo{405d44c0 #2147483647 : ImageLoader{405118a8}}
11-03 13:33:34.920: V/LoaderManager(14313): Destroying: LoaderInfo{405d44c0 #2147483647 : ImageLoader{405118a8}}
11-03 13:33:34.920: V/LoaderManager(14313): Enqueuing as new pending loader
के आधार पर हो तो फिर मैंने सोचा कि शायद प्रत्येक लोडर के लिए अद्वितीय आईडी देने मामलों में मदद मिलेगी, लेकिन यह कोई फर्क नहीं लगती है। नतीजतन मैं प्रतीत होता है कि यादृच्छिक छवियों के साथ समाप्त होता है और ऐप मुझे जो भी चाहिए उसे 1/4 भी लोड नहीं करता है।
प्रश्न
- क्या तरीका लोडर ठीक करने के लिए मैं क्या करना चाहते हैं (और वहाँ एक रास्ता है?)
- होगा यदि नहीं एक अच्छा तरीका
AsyncTask
पूल बनाने के लिए क्या है और है शायद इसके कार्यान्वयन का काम कर रहे हैं?
आपको कोड के विचार को लोडर के छीनने वाले संस्करण के बारे में जानकारी देने के लिए जहां वास्तविक डाउनलोड/सहेजें तर्क अलग छवि प्रबंधक वर्ग में है।
public class ImageLoader extends AsyncTaskLoader<TaggedDrawable> {
private static final String TAG = ImageLoader.class.getName();
/** Wrapper around BitmapDrawable that adds String field to id the drawable */
TaggedDrawable img;
private final String url;
private final File cacheDir;
private final HttpClient client;
/**
* @param context
*/
public ImageLoader(final Context context, final String url, final File cacheDir, final HttpClient client) {
super(context);
this.url = url;
this.cacheDir = cacheDir;
this.client = client;
}
@Override
public TaggedDrawable loadInBackground() {
Bitmap b = null;
// first attempt to load file from SD
final File f = new File(this.cacheDir, ImageManager.getNameFromUrl(url));
if (f.exists()) {
b = BitmapFactory.decodeFile(f.getPath());
} else {
b = ImageManager.downloadBitmap(url, client);
if (b != null) {
ImageManager.saveToSD(url, cacheDir, b);
}
}
return new TaggedDrawable(url, b);
}
@Override
protected void onStartLoading() {
if (this.img != null) {
// If we currently have a result available, deliver it immediately.
deliverResult(this.img);
} else {
forceLoad();
}
}
@Override
public void deliverResult(final TaggedDrawable img) {
this.img = img;
if (isStarted()) {
// If the Loader is currently started, we can immediately deliver its results.
super.deliverResult(img);
}
}
@Override
protected void onStopLoading() {
// Attempt to cancel the current load task if possible.
cancelLoad();
}
@Override
protected void onReset() {
super.onReset();
// Ensure the loader is stopped
onStopLoading();
// At this point we can release the resources associated with 'apps'
// if needed.
if (this.img != null) {
this.img = null;
}
}
}
'AsyncTask' पहले से ही पूल का उपयोग करता है। पूल आईआईआरसी 128 धागे तक जाता है, जो आपकी कठिनाई का स्रोत हो सकता है। आप 'java.util.concurrent' कक्षाओं का उपयोग करके अपने स्वयं के थ्रेड पूल को हमेशा कार्यान्वित कर सकते हैं। – CommonsWare
यदि आपका विकास एंड्रॉइड 3.0 (एपीआई लेवल 11) को लक्षित कर रहा है, तो आप नए जोड़े गए एपीआई [AsyncTask.executeOnExecutor()] का उपयोग कर सकते हैं (http://developer.android.com/reference/android/os/AsyncTask.html#executeOnExecutor% 28java.util.concurrent.Executor,% 20 पैराम ...% 2 9) अपने थिंक पूल को अपने AsyncTask निर्माण जीवन चक्र के साथ ठीक से नियंत्रित करें। – yorkw
AsynkTask फिर भी केवल एक बार निष्पादित किया जा सकता है इसलिए मुझे प्रति छवि एक उदाहरण बनाने की आवश्यकता है जिसे मैं लोड कर रहा हूं। इसे 60 बनाएं और यह बहुत सारी ऑब्जेक्ट्स – Bostone