正确释放属于适配器的视图中的资源

时间:2014-12-05 03:04:14

标签: android listview memory-leaks android-view

我的列表适配器会创建一些Views(正常视图和标题视图)使用不断运行的计时器来循环显示的图像。

我想知道取消分配这些计时器和其他与视图相关的资源的适当方法是什么,我的意思是,最好的做法是知道项目View(由Adapter.getView创建)不再可见/需要,或已经被回收或去附加,甚至他们的父小部件都没有被使用。

我理想地在View本身中寻找方法/事件/侦听器,而不是必须委托事件的父Widget。我想知道

  • 当给予回收者View时(即它已经退出屏幕等)
  • View可以被销毁时(即 - 包含的小部件已被销毁)

到目前为止,我认为我没有找到适当的,防止失败的事件,如果有的话。

我尝试了View.onAttachedToWindow() / View.onDetachedFromWindow(),但是,与onAttachedToWindow相反,似乎总是被正确调用,onDetachedFromWindow不是。 似乎仅在回收视图即将重复使用时调用,而不是在View进入回收池(退出屏幕)或者小部件被销毁时等其他情况下调用,甚至活动结束时。

有什么建议吗?

编辑:

我一直在做一些测试,发现父窗口小部件上的onDetachedFromWindow是可靠的。目前,我的解决方案是将该事件传播到适配器,后者又在屏幕上查找视图(getFirstVisiblePosition ...)并手动触发onDetachedFromWindow下面的代码,但是,你知道,这非常难看。我确信有更好的方法。

// ugly function to trigger an onDetachedFromWindow to any view
// leeched from com.tonicartos.widget.stickygridheaders.StickyGridHeadersGridView
public static void detachHeader(View header) {
    if (header == null) { return; }

    try {
        Method method = View.class.getDeclaredMethod("dispatchDetachedFromWindow");
        method.setAccessible(true);
        method.invoke(header);
    } catch (NoSuchMethodException e) {
        throw new RuntimePlatformSupportException(e);
    } catch (IllegalArgumentException e) {
        throw new RuntimePlatformSupportException(e);
    } catch (IllegalAccessException e) {
        throw new RuntimePlatformSupportException(e);
    } catch (InvocationTargetException e) {
        throw new RuntimePlatformSupportException(e);
    }
}

2 个答案:

答案 0 :(得分:0)

RecyclerView.Adapter有一种方法可以在回收视图时通知您。看看

public void onViewRecycled(RecyclerView.ViewHolder holder);

答案 1 :(得分:0)

a)离开活动-刷新adpater中的所有内容

也许正确的方法是使用周围活动的onStop方法。那里确实有对适配器的引用。在适配器中,您可以提供从活动中调用的flushAllResources()方法。 这将在有人离开活动的情况下起作用。

@Override
public void onViewRecycled(@NonNull final MyViewHolder holder) {
    flushAllViewRefreshHandlers();
}

b)由于滚动,视图将被重新使用-以前使用视图时刷新旧数据

此外,在onViewRecycled方法中(如前所述),您还应该刷新资源。 对于回收者的单个项目/视图将被其他实体重新使用(回收)的情况,这将起作用。在这种情况下,您只能刷新特定视图/实体的数据,而不能刷新整个适配器的全部数据。