【问题标题】:Detect item view on Adapter has been destroyed检测适配器上的项目视图已被破坏
【发布时间】:2013-03-07 17:33:26
【问题描述】:

我有一个带有 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 被回收时被调用。

谢谢!

【问题讨论】:

  • 聚会迟到但可能会帮助别人。适配器中的onViewDetachedFromWindow(holder: RepositoryViewHolder) 可以满足问题的要求。

标签: android listview adapter baseadapter


【解决方案1】:

根据this offical issueonViewDetachFromWindow BUT 存在问题

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

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

【讨论】:

    【解决方案2】:

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

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

    编辑

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

    最大的问题是视图被适配器重用。当您向下滚动列表时,最上面的项目视图被重用(而不是销毁!)以显示最下面的项目视图。如果您覆盖适配器的 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);
    

    【讨论】:

    • 同样的问题。我尝试覆盖 onDetachedFromWindow,但是当我上下滚动时它从未被调用过。
    • 我的意思是项目视图应该扩展android View,而不是ListView。
    猜你喜欢
    • 1970-01-01
    • 2016-11-03
    • 2014-08-24
    • 2017-11-19
    • 2013-12-01
    • 2013-10-01
    • 1970-01-01
    • 2020-03-18
    • 2018-06-08
    相关资源
    最近更新 更多