检测到适配器上的项目视图已被破坏

时间:2013-03-07 17:33:26

标签: android listview adapter baseadapter

我有一个带BaseAdapter的ListView。我想经常更新列表中的一些项目而不刷新内容。为了实现这一点,我正在使用Observer模式。我有一个Observable对象,列表中的每个项目都是观察者。

    public View getView(final int position, View convertView, final ViewGroup parent) {
        final ItemViewHolder holder;
        final Item item = (Item) getItem(position);
        if (convertView == null) {
            convertView = inflater.inflate(R.layout.item, parent, false);

            /* ADD VIEWS TO HOLDER */

            holder = new ItemViewHolder();

            convertView.setTag(holder);

            ItemObserver observer = new ItemObserver(holder, context);
            mapObservers.put(holder, observer);
            observable.addObserver(observer);
        } else {
            holder = (ItemViewHolder) convertView.getTag();
        }
        //Set values into view etc...
        return convertView;
    }

这很有效,但问题是:我怎么知道不再需要观察者?我想检测给定视图何时被销毁,以便从Map获取观察者并从Observable对象中删除它。在视图被销毁时是否有任何侦听器?

我尝试了AbsListView.RecyclerListener.onMovedToScrapHeap(View view)但似乎在回收View时调用了它。

谢谢!

2 个答案:

答案 0 :(得分:4)

根据this offical issueonViewDetachFromWindow

存在问题
  

onDetachedFromWindow()不一定会在此调用   情况。列表显示   孩子们被回收和重复使用,ListView避免了不必要的   尽可能使用onDetachedFromWindow()   但是,onDetachedFromWindow()   应该在销毁Activity时调用适配器创建的所有视图   当ListView与窗口分离时。

所以你不能指望列表视图被销毁。

答案 1 :(得分:2)

您的项目视图必须扩展android视图并覆盖下一个方法:

@Override
protected void onDetachedFromWindow() {
    super.onDetachedFromWindow();
    // View is now detached, and about to be destroyed.
    // Remove observer here.
}

修改

阅读完评论后,我决定解释一下列表视图的工作原理。

最大的问题是适配器正在重用视图。向下滚动列表时,最重要的项目视图将被重复使用(不会被销毁!)以显示最低的项目视图。如果覆盖适配器的getView()方法,则会在下一个方法中反映出来:

public View getView(int position, View convertView, ViewGroup parent) {
    View view = super.getView(position, convertView, parent);
    ...
    return view;
}

它背后的作用:

    if (convertView == null) {
        view = mInflater.inflate(resource, parent, false);
    } else {
       view = convertView;
    }

因此,convertView永远不会被破坏,但重用。回到问题,您应该根据变量位置更新持有者值,在行之后:

    holder = (ItemViewHolder) convertView.getTag();
    // Update your holder/observer here. Something like:
    holder.setPosition(position);