本文选自系列文章之一,本系列文章将为读者分享国外最优质的精彩问与答,供读者学习和了解国外最新技术。本文将为读者讲解滚动ListView时图像顺序混乱的解决方法。
问题:
ListView有两个TextViews 和一个ImageView。图片是从网上下载的,缓存在LruCache。当在ListView滚动时,图片会出现几秒钟的混乱。直到正确的图片完全加载之前是不应该有任何图片出现的。我发现了几个同样的问题,但是没人能帮助我。
这是我的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | 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); } } } |
如果谁能帮助我那就太好了!先谢过!
PS:我忘记了一些东西,请不要建议任何库,我想在不使用外部库的情况下完成它。
答案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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 | ViewHolder viewHolder = new ViewHolder(); |
这个片段是在每次调用getView的时候,创建viewHolder的新实例。
试试用这个来代替:
1 | final ViewHolder viewHolder; |
然后在if结构中:
1 | viewHolder = new ViewHolder(); |
执行你的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | @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; } |
原文链接:
文章选自社区,鉴于其内容对于开发者有所帮助,现将文章翻译于此,供大家参考及学习。9Tech将每日持续更新,读者可点击,查看全部译文内容。同时,我们也招募志同道合的技术朋友共同翻译,造福大家!报名请发邮件至zhangqi_wj#cyou-inc.com。(#换成@)