Bos*_*one 7 android threadpool android-fragments asynctaskloader
首先是问题:
FragmentLists
自定义中使用多个的应用程序FragmentStatePagerAdapter.可能有大量此类碎片在20到40之间.我的第一个实现遵循着名的谷歌图像加载器代码.我的代码问题是它基本上创建了AsyncTask每个图像的一个实例.在我的情况下,这快速杀死应用程序.
由于我使用的是v4兼容包,我认为使用扩展的自定义Loader AsyncTaskLoader会对我有所帮助,因为它内部实现了一个线程池.但令我不愉快的是,如果我执行此代码多次,每次调用后都会中断前一次.说我的ListView#getView方法中有这个:
getSupportLoaderManager().restartLoader(0, args, listener);
Run Code Online (Sandbox Code Playgroud)
对于进入视图的每个列表项,在循环中执行此方法.正如我所说 - 以下每次调用都会终止前一个调用.或者至少这是基于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
Run Code Online (Sandbox Code Playgroud)
然后我认为可能给每个装载机提供唯一的ID将有助于事情,但它似乎没有任何区别.结果我最终得到看似随机的图像,应用程序永远不会加载我需要的1/4.
问题
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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
Bri*_*fey 11
好的,首先要做的事情.Android附带的AsyncTask不应该淹没你的应用程序或导致它崩溃.AsyncTasks在线程池中运行,其中最多有5个线程同时实际执行.虽然您可以排队许多要执行的任务,但一次只执行其中的5个任务.通过在后台线程池中执行它们,它们根本不会对您的应用程序产生任何影响,它们应该可以顺利运行.
如果您对AsyncTask加载程序性能不满意,则使用AsyncTaskLoader无法解决您的问题.AsyncTaskLoader只接受加载器接口并将其与AsyncTask结合.所以它实际上映射onLoadFinished - > onPostExecute,onStart - > onLoadInBackground.所以它是完全相同的.
我们为我们的app使用相同的图像加载器代码,每次我们尝试加载图像时都会将asynctask放到线程池队列中.在谷歌的示例中,他们将imageview与其异步任务相关联,以便他们可以在尝试在某种适配器中重用imageview时取消异步任务.你应该在这里采取类似的策略.您应该将imageview与异步任务相关联,即在后台加载图像.当您有一个未显示的片段时,您可以循环浏览与该片段关联的图像视图并取消加载任务.简单地使用AsyncTask.cancel()应该可以正常工作.
您还应该尝试实现异步图像视图示例拼写出来的简单图像缓存机制.我们只需创建一个来自url - > weakreference的静态hashmap.这样,图像可以在需要时被回收,因为它们仅以弱引用保持.
这是我们所做的图像加载的概述
public class LazyLoadImageView extends ImageView {
public WeakReference<ImageFetchTask> getTask() {
return task;
}
public void setTask(ImageFetchTask task) {
this.task = new WeakReference<ImageFetchTask>(task);
}
private WeakReference<ImageFetchTask> task;
public void loadImage(String url, boolean useCache, Drawable loadingDrawable){
BitmapDrawable cachedDrawable = ThumbnailImageCache.getCachedImage(url);
if(cachedDrawable != null){
setImageDrawable(cachedDrawable);
cancelDownload(url);
return;
}
setImageDrawable(loadingDrawable);
if(url == null){
makeDownloadStop();
return;
}
if(cancelDownload(url)){
ImageFetchTask task = new ImageFetchTask(this,useCache);
this.task = new WeakReference<ImageFetchTask>(task);
task.setUrl(url);
task.execute();
}
......
public boolean cancelDownload(String url){
if(task != null && task.get() != null){
ImageFetchTask fetchTask = task.get();
String downloadUrl = fetchTask.getUrl();
if((downloadUrl == null) || !downloadUrl.equals(url)){
fetchTask.cancel(true);
return true;
} else
return false;
}
return true;
}
}
Run Code Online (Sandbox Code Playgroud)
因此,只需旋转片段中的图像视图,然后在片段隐藏时取消它们,并在片段可见时显示它们.
| 归档时间: |
|
| 查看次数: |
5253 次 |
| 最近记录: |