第一問題:Android - 線程池策略和可以用Loader來實現它嗎?
- 我正在使用自定義
FragmentStatePagerAdapter
內的多個FragmentLists
應用。可能有, 潛在大量的這樣的片段說20至40之間。 - 每個片段是一個列表,其中每個項目可能包含文本或圖像。
- 的圖像需要從網絡異步上傳並緩存到臨時內存緩存,併爲SD(如果可用)
- 當片段熄滅屏幕任意上傳和當前活動應取消(不暫停)
我的第一個實現遵循Google公司的image loader code。我的代碼問題是,它基本上爲每個圖像創建一個AsyncTask
的實例。在我的情況下,殺死應用程序真的很快。
由於我使用的是v4兼容包,我認爲使用定製的Loader擴展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
然後我想,也許給唯一的ID給每個裝載機將有助於問題,但它似乎並沒有任何區別。結果,我看起來隨機的圖像和應用程序永遠不會加載我所需要的四分之一。
問題
- 什麼是修復裝載機做我想做什麼(有沒有辦法?)
- 的方式,如果沒有什麼是創造
AsyncTask
池的好辦法,是那裏可能正在執行它?
爲了讓您知道這裏的代碼是精簡版的Loader,其中實際的下載/保存邏輯位於單獨的ImageManager類中。
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個線程IIRC,這可能是您難度的來源。你可以使用'java.util.concurrent'類來實現你自己的線程池。 – CommonsWare
如果您的開發針對Android 3.0(API Level 11),則可以使用新添加的API [AsyncTask.executeOnExecutor()](http://developer.android.com/reference/android/os/AsyncTask.html#executeOnExecutor% 28java.util.concurrent.Executor,%20Params ...%29)可以很好地控制你的AsyncTask創建生命週期的線程池。 – yorkw
AsynkTask不過只能執行一次,所以我需要爲每個加載的圖像創建一個實例。使它60,這是很多的對象 – Bostone