我有一个ListFragment,可以异步加载多个图像,但它的表现方式很奇怪as you can see here。
这是AsyncTask代码
public class BitmapWorkerClass extends AsyncTask<Integer, Void, Bitmap>
{
private Context context;
private final WeakReference<ImageView> imageViewWeakReference;
private int data = 0;
public BitmapWorkerClass(ImageView imageView, Context context)
{
this.context = context.getApplicationContext();
imageViewWeakReference = new WeakReference<ImageView>(imageView);
}
@Override
protected Bitmap doInBackground(Integer... params) {
data = params[0];
return ImageResizer.decodeSampledBitmapFromResource(context.getResources(), data, 100,100);
}
@Override
public void onPostExecute(Bitmap bitmap)
{
if(imageViewWeakReference != null && bitmap != null)
{
final ImageView imageView = imageViewWeakReference.get();
if(imageView != null)
{
imageView.setImageBitmap(bitmap);
}
}
}
}
我从ListFragment适配器的getView()方法
中调用它public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if(convertView == null)
{
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.list_fragment_single_recipe_title, null);
holder = new ViewHolder();
holder.image = (ImageView) convertView.findViewById(R.id.recipeTitleImage);
holder.title = (TextView) convertView.findViewById(R.id.recipeTitleText);
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}
Recipe recipe = getItem(position);
loadBitmap(recipe.getImage(), holder.image);
holder.title.setText(recipe.getTitle());
return convertView;
public void loadBitmap(int resId, ImageView imageView)
{
BitmapWorkerClass task = new BitmapWorkerClass(imageView, getContext());
task.execute(resId);
}
你能帮助我理解AsyncTask在视频中的表现吗?
提前致谢
答案 0 :(得分:4)
您可能正在循环中添加数据并在循环中调用notifyDataSetChanged(),或者您正在使用ArrayAdapters add()方法。您可能还会以不同于显示的顺序添加数据。
因此convertView被回收。这导致多次调用同一项的getView()。
这会导致BitmapWorkerClass的多个实例对同一个ImageView实例具有WeakReference。它们中的每一个都在某个时刻结束并调用OnPostExecute(),从而导致随机效应。
使用WeakReference(不推荐使用btw)可以帮助解决内存泄漏问题,但它对View-recycling没有帮助。下面的代码应该可以解决您遇到的问题,但这可能不是最有效的方法。
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if(convertView == null)
{
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.list_fragment_single_recipe_title, null);
holder = new ViewHolder();
holder.image = (ImageView) convertView.findViewById(R.id.recipeTitleImage);
holder.title = (TextView) convertView.findViewById(R.id.recipeTitleText);
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}
Recipe recipe = getItem(position);
// cancel the previous asynctask if there was any
if (holder.asynctask != null) {
holder.asynctask.cancel(false);
// you could pass true, but would have to handle the interruption then
}
// remove the previous image, you could set a default or loading image here instead
holder.image.setImageDrawable(null);
holder.asynctask = loadBitmap(recipe.getImage(), holder.image);
holder.title.setText(recipe.getTitle());
return convertView;
}
public BitmapWorkerClass loadBitmap(int resId, ImageView imageView)
{
BitmapWorkerClass task = new BitmapWorkerClass(imageView, getContext());
task.execute(resId);
return task;
}
public static class ViewHolder {
ImageView image;
TextView title;
BitmapWorkerClass asynctask; // save a reference to the asynctask
}