第一问题: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