Knowing when a View in a ListView has gone off the screen?

后端 未结 4 1030
醉梦人生
醉梦人生 2020-12-30 23:36

I have Googled this but can\'t find an answer, so here goes...

I have a ListView that displays some text and an image. The underlying adapter recycles the views for

相关标签:
4条回答
  • 2020-12-31 00:16

    If you use a LruCache for the bitmaps and have each view in the listview keep the key to the LruCache item, you can control it better.. Then, in getView, you first try and get the bitmap from the LruCache and only download it again if it is not there.

    Also, you can set an setOnScrollListener() on the ListView, and use its visibleItemCount parameter to adjust the size of the LruCache the first time the user scrolls.

    0 讨论(0)
  • 2020-12-31 00:19

    if you are using overrided getView method for display images so you can check convertView. if it was null then you can found that it recycled or it is not initialized before. simply like this:

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
        // TODO Auto-generated method stub
        ViewHolder viewholder;
        if (convertView == null) {
            viewholder = new ViewHolder();
            inflater = (LayoutInflater) context
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = inflater.inflate(R.layout.item_row, parent, false);
            viewholder.tvID = (TextView) convertView.findViewById(R.id.tvID);
            viewholder.tvName = (TextView) convertView.findViewById(R.id.tvName);
            viewholder.tvFamily = (TextView) convertView.findViewById(R.id.tvFamily);
            viewholder.ivMain = (ImageView) convertView.findViewById(R.id.ivMain);
        } else {
            viewholder = (ViewHolder) convertView.getTag();
        }
        viewholder.tvID.setText(IDs[position]);
        viewholder.tvName.setText(Names[position]);
        viewholder.tvFamily.setText(Familys[position]);
        viewholder.ivMain.setImageResource(Images[position]);
        convertView.setTag(viewholder);
        return convertView;
    }
    
    0 讨论(0)
  • 2020-12-31 00:36

    There is actually a simpler way to do that, you can use a listener :

    mListView.setRecyclerListener(new AbsListView.RecyclerListener() {
    @Override
        public void onMovedToScrapHeap(View view) {
      }
    });
    
    0 讨论(0)
  • 2020-12-31 00:40

    Can't believe how stupid I have been, this is a really easy one liner to solve!

    Basically in my adapter if the view is being re-cycled, I simply need to null the ImageView bitmap before the view is re-used. That means the image in the list view item is blank before the next image is loaded. I no longer have the issue of the old image being there whilst the new image is being loaded in the background.

    I have also made a change in the adapter that cancels any current AsynchTask bound to the view that might still be loading a previous image that is no longer needed. This was very prevalent when I scroll very fast through the list view, with often two or more image loads backing up, so the image would change several times before settling on the correct image.

    Here is the new code, with the changes commented so you can see what is happening:

    @Override
    public View getView(int position, View convertView, ViewGroup parent)
    {
        ListViewHolder viewHolder;
    
        // if this is not a recycled view then create a new view for the data...
        if (convertView == null)
        {
            convertView = this.inflater.inflate(R.layout.target_list_view_layout, null, true);
    
            viewHolder = new ListViewHolder();
    
            viewHolder.manufacturer = (TextView) convertView.findViewById(R.id.manufacturer);
            viewHolder.targetName = (TextView) convertView.findViewById(R.id.targetName);
            viewHolder.targetThumbnail = (ImageView) convertView.findViewById(R.id.targetThumbnail);
    
            convertView.setTag(viewHolder);
        } else
        {
            viewHolder = (ListViewHolder) convertView.getTag();
    
            // Cancel the previous attempt to load an image as this is going to be superceded by the next image
            viewHolder.loadImageViewAsynchTask.cancel(true);
    
            // Clear down the old image so when this view is displayed, the user does not see the old image before the
            // new image has a chance to load in the background
            viewHolder.targetThumbnail.setImageBitmap(null);
        }
    
        TargetDescriptor targetDescriptor = this.selectedTargets.get(position);
    
        viewHolder.manufacturer.setText(targetDescriptor.manufacturer);
        viewHolder.targetName.setText(targetDescriptor.targetName);
    
        LoadImageViewAsynchTask loadImageViewAsynchTask = new LoadImageViewAsynchTask(viewHolder.targetThumbnail);
        loadImageViewAsynchTask.setTargetDescriptor(targetDescriptor);
        loadImageViewAsynchTask.execute(new Integer[]
        { 64, 64 });
    
        // Keep a reference to the task so we can cancel it if the view is recycled next time round to prevent
        // un-neccessary image loads that are out of date
        viewHolder.loadImageViewAsynchTask = loadImageViewAsynchTask;
    
        return convertView;
    }
    
    0 讨论(0)
提交回复
热议问题