4

我有一个带有 BaseAdapter 的 ListView。我想经常更新列表中的某些项目而不刷新内容。为了实现这一点,我使用了观察者模式。我有一个 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 被回收时被调用。

谢谢!

4

2 回答 2

5

根据这个官方问题onViewDetachFromWindowBUT存在问题

在这种情况下,不一定会调用 onDetachedFromWindow()。ListView 子项被回收和重用,ListView 尽可能避免不必要的 onDetachedFromWindow()。
但是,当 Activity 被销毁或 ListView 与窗口分离时,应为适配器创建的所有视图调用 onDetachedFromWindow()。

所以你不能指望 listview 视图被破坏。

于 2015-07-30T09:22:02.237 回答
3

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

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

编辑

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

最大的问题是视图被适配器重用。当您向下滚动列表时,最上面的项目视图被重用(而不是销毁!)以显示最下面的项目视图。如果您覆盖适配器的 getView() 方法,这将反映在 next 方法中:

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 永远不会被破坏,而是被重用。回到问题上来,您只需要根据变量position更新持有者值,在以下行之后:

    holder = (ItemViewHolder) convertView.getTag();
    // Update your holder/observer here. Something like:
    holder.setPosition(position);
于 2013-06-11T14:56:21.367 回答