我使用ASyncTask在我的GridView布局中加载缩略图,但是当我刷新数据时,缩略图以奇数顺序加载。它总是首先加载最后一个元素,但它使用第一个元素缩略图渲染它,然后使用适当的缩略图(最后的元素)重新渲染它,然后它正确加载从第一个到倒数第二个的每个其他缩略图。它还会多次重新加载图像,加载时速度相当慢(但是16mp图像)
这是我的GridView适配器(带有ASyncTask)。
public class ReceiptListAdapter extends ArrayAdapter {
public ReceiptListAdapter(Context context, ArrayList<Receipt> receipts){
super(context, 0, receipts);
// getItem(1);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// Get the data item for this position
// Check if an existing view is being reused, otherwise inflate the view
ViewHolder holder;
// Lookup view for data population
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.receipt_list_element, parent, false);
holder = new ViewHolder();
// Populate the data into the template view using the data object
holder.title = (TextView) convertView.findViewById(R.id.TitleView);
holder.date = (TextView) convertView.findViewById(R.id.DateView);
holder.image = (ImageView) convertView.findViewById(R.id.containerImage);
holder.spn = (ProgressBar) convertView.findViewById(R.id.spinner);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
Receipt receipt = (Receipt) getItem(position);
holder.imagePath = receipt.getFilepath();
final int tWidth = receipt.getWidth();
// manipulate data here...
holder.spn.setVisibility(View.VISIBLE);
holder.image.setVisibility(View.GONE);
holder.title.setText(receipt.getDesc());
new AsyncTask<ViewHolder, Void, Bitmap>() {
private ViewHolder h;
@Override
protected Bitmap doInBackground(ViewHolder... t) {
h = t[0];
Bitmap thumb = ExifUtil.rotateBitmap(h.imagePath, ThumbnailUtils.extractThumbnail(
BitmapFactory.decodeFile(h.imagePath),
tWidth,
tWidth));
return thumb;
}
@Override
protected void onPostExecute(Bitmap result) {
super.onPostExecute(result);
h.spn.setVisibility(View.GONE);
h.image.setVisibility(View.VISIBLE);
h.image.setImageBitmap(result);
}
}.execute(holder);
// Return the completed view to render on screen
return convertView;
}
static class ViewHolder {
private TextView title;
private TextView date;
private ImageView image;
private String imagePath;
private ProgressBar spn;
}
}
答案 0 :(得分:1)
我只是使用另一个库,但让我解释一些问题的来源。首先按照AsyncTask
首次引入时,AsyncTasks在单个后台线程上串行执行。从DONUT开始,这被改为一个线程池,允许多个任务并行运行。从HONEYCOMB开始,任务在单个线程上执行,以避免由并行执行引起的常见应用程序错误。
这意味着您一次只能加载1个缩略图。你的第二个问题是因为viewHolder实际上是重用的。您为同一视图创建2个AsyncTasks,它们在不同的时间执行(但顺序正确)。这可以通过保持对任务的引用并在创建新任务之前停止它来解决。
答案 1 :(得分:1)
我已用Glide库替换您的AsyncTask更新您的代码 下面
public class ReceiptListAdapter extends ArrayAdapter {
public ReceiptListAdapter(Context context, ArrayList<Receipt> receipts){
super(context, 0, receipts);
// getItem(1);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// Get the data item for this position
// Check if an existing view is being reused, otherwise inflate the view
ViewHolder holder;
// Lookup view for data population
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.receipt_list_element, parent, false);
holder = new ViewHolder();
// Populate the data into the template view using the data object
holder.title = (TextView) convertView.findViewById(R.id.TitleView);
holder.date = (TextView) convertView.findViewById(R.id.DateView);
holder.image = (ImageView) convertView.findViewById(R.id.containerImage);
holder.spn = (ProgressBar) convertView.findViewById(R.id.spinner);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
Receipt receipt = (Receipt) getItem(position);
holder.imagePath = receipt.getFilepath();
final int tWidth = receipt.getWidth();
// manipulate data here...
holder.spn.setVisibility(View.VISIBLE);
holder.image.setVisibility(View.GONE);
holder.title.setText(receipt.getDesc());
Glide.with(context)
.load(holder.imagePath)
.into(holder.image);
/*new AsyncTask<ViewHolder, Void, Bitmap>() {
private ViewHolder h;
@Override
protected Bitmap doInBackground(ViewHolder... t) {
h = t[0];
Bitmap thumb = ExifUtil.rotateBitmap(h.imagePath, ThumbnailUtils.extractThumbnail(
BitmapFactory.decodeFile(h.imagePath),
tWidth,
tWidth));
return thumb;
}
@Override
protected void onPostExecute(Bitmap result) {
super.onPostExecute(result);
h.spn.setVisibility(View.GONE);
h.image.setVisibility(View.VISIBLE);
h.image.setImageBitmap(result);
}
}.execute(holder);*/
// Return the completed view to render on screen
return convertView;
}
static class ViewHolder {
private TextView title;
private TextView date;
private ImageView image;
private String imagePath;
private ProgressBar spn;
}
}
打开
build.gradle
并添加此依赖项
compile 'com.github.bumptech.glide:glide:4.0.0-RC0'
答案 2 :(得分:0)
我不会直接解决这个问题,而是提出两件事: 1.使用RecyclerView和RecyclerView.Adapter而不是现在拥有的。 2.使用像Picasso或Glide这样的图像加载库,而不是将其加载到AsyncTask中。在自己异步加载东西时要考虑很多事情,并且库已经处理了许多可能的错误。
在此处了解如何使用RecyclerView实现ViewHolder模式:https://guides.codepath.com/android/using-the-recyclerview