ListView - 滚动时图像随机播放

时间:2013-12-24 14:51:22

标签: android listview asynchronous imageview

我有一个带有两个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。:我忘记了什么,请不要建议任何库,我想在没有任何外部库的情况下这样做。

2 个答案:

答案 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;
}