我有一个带有两个TextView和一个ImageView的ListView。图像从Internet加载并由LruCache缓存。滚动浏览ListView时,图像会被洗牌几秒钟。在正确的图像完全加载之前,不应该是任何图像。我发现了几个同样问题的问题,但没有人帮助过我:/。这是我的代码:
public class NewsAdapter extends BaseAdapter {
private static LayoutInflater inflater;
private List<Item> items = new LinkedList<Item>();
private LruCache<String, Bitmap> mMemoryCache;
public NewsAdapter(Context context) {
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// Bitmap Cache
final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
final int cacheSize = maxMemory / 8;
mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {
@Override
protected int sizeOf(String key, Bitmap bitmap) {
return getSizeInBytes(bitmap) / 1024;
}
};
}
public void add(Item item) {
items.add(item);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder = new ViewHolder();
if(convertView == null) {
convertView = inflater.inflate(R.layout.list_item_item, null);
viewHolder.ivPic = (ImageView) convertView.findViewById(R.id.ivPic);
viewHolder.tvTitle = (TextView) convertView.findViewById(R.id.tvTitle);
viewHolder.tvShortDesc = (TextView) convertView.findViewById(R.id.tvShortDesc);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
final Item item = items.get(position);
viewHolder.tvTitle.setText(item.getTitle());
viewHolder.tvShortDesc.setText(Html.fromHtml(item.getShortDesc()));
Bitmap bitmap = mMemoryCache.get(item.getPicUrl());
if (bitmap != null) {
viewHolder.ivPic.setImageBitmap(bitmap);
} else {
GetBitmap gb = new GetBitmap(item.getPicUrl(), viewHolder.ivPic);
gb.execute();
}
return convertView;
}
static class ViewHolder {
ImageView ivPic;
TextView tvTitle;
TextView tvShortDesc;
}
@Override
public int getCount() {
return items.size();
}
@Override
public Item getItem(int position) {
return items.get(position);
}
@Override
public long getItemId(int position) {
return 0;
}
@SuppressLint("NewApi")
public static int getSizeInBytes(Bitmap bitmap) {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
return bitmap.getByteCount();
} else {
return bitmap.getRowBytes() * bitmap.getHeight();
}
}
private class GetBitmap extends AsyncTask<Void, Bitmap, Bitmap> {
private String url;
private ImageView ivPic;
public GetBitmap(String url, ImageView ivPic) {
this.url = url;
this.ivPic = ivPic;
}
@Override
protected Bitmap doInBackground(Void... params) {
Bitmap bitmap = null;
try {
URL url = new URL(this.url);
bitmap = BitmapFactory.decodeStream(url.openConnection().getInputStream());
} catch (Exception e) {
e.printStackTrace();
}
return bitmap;
}
@Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
if (bitmap != null) ivPic.setImageBitmap(bitmap);
}
}
}
如果有人有想法会很高兴...提前致谢!
P.S。:我忘记了什么,请不要建议任何库,我想在没有任何外部库的情况下这样做。
答案 0 :(得分:3)
public GetBitmap(String url, ImageView ivPic, int position) {
this.url = url;
this.ivPic = ivPic;
this.position = position;
ivPic.setTag(position);
ivPic.setImageBitmap(null);
}
@Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
if(bitmap != null && ((Integer)getTag) == this.position)
ivPic.setImageBitmap(bitmap);
}
问题是您没有检查图像是否处于相同位置。试试上面的代码希望它会有所帮助。
答案 1 :(得分:0)
可能是这个代码片段
ViewHolder viewHolder = new ViewHolder();
这就是每次调用getView时都会创建一个新的viewHolder实例。
请改为尝试:
final ViewHolder viewHolder;
然后在if-structure
中 viewHolder = new ViewHolder();
在您的代码中实现:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final ViewHolder viewHolder;
if(convertView == null) {
convertView = inflater.inflate(R.layout.list_item_item, null);
viewHolder = new ViewHolder();
viewHolder.ivPic = (ImageView) convertView.findViewById(R.id.ivPic);
viewHolder.tvTitle = (TextView) convertView.findViewById(R.id.tvTitle);
viewHolder.tvShortDesc = (TextView) convertView.findViewById(R.id.tvShortDesc);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
final Item item = items.get(position);
viewHolder.tvTitle.setText(item.getTitle());
viewHolder.tvShortDesc.setText(Html.fromHtml(item.getShortDesc()));
Bitmap bitmap = mMemoryCache.get(item.getPicUrl());
if (bitmap != null) {
viewHolder.ivPic.setImageBitmap(bitmap);
} else {
GetBitmap gb = new GetBitmap(item.getPicUrl(), viewHolder.ivPic);
gb.execute();
}
return convertView;
}