6

Can the RecyclerView.ViewHolder be used not as a inner class? Are there any issues on doing so?

I have searched around but havent found any documentation on it!

4

1 回答 1

9

实际上,我认为 ViewHolder 应该是静态嵌套类(注意静态!)或顶级类(实际上没有什么不同,只是类名将包含外部类名,后跟 $,然后内部类名)。

为什么我会这么认为?当 ViewHolder 是适配器的非静态内部类时,它会保留对适配器的引用。现在,当您调用 RecyclerView.swapAdapter(newAdapter, false) (或者是真的吗?我不记得了)时,新适配器将使用旧适配器之前创建的 ViewHolders。由于不可能在这些持有者中清空/清除此类隐式引用,因此对第一个适配器的此引用已泄漏并且无法被垃圾收集。这已经够糟糕的了。

但是,就我而言,我遇到了与记忆无关的实际问题。My adapter had a 'selection model' which kept position-to-data mapping and the view holder would use the data when it shown the item (like for instance, when the selection model said the item at position 17 is selected, when it was在屏幕上绘制,它的字体颜色会改变)为用户标记它。它通过从适配器访问选择模型字段来做到这一点,这在 Java 中意味着它使用对封闭适配器实例的隐式引用,而不是访问其字段。现在,在 swapAdapter 之后,保留的 ViewHolders 仍在使用适配器的选择模型,并且 UI 已损坏,因为某些项目会显示为已选择,而在新模型中它们不是。

本质上,对于这样的非静态内部类持有者来说,他们不可能真正忘记旧的适配器并使用新的适配器,因为没有办法清除隐式引用。

对此有很多解决方案,其中之一是 ViewHolder 是一个静态嵌套类,并且在它绑定时显式地给它一个对适配器的引用,并在它取消绑定时将其设为 null。我一直在为我的视图持有者使用顶级类,并明确引用适配器,我认为这就是您要问的。请注意,持有者通常根本不需要对其适配器的任何引用,因此您可能根本不需要设置适配器。

当然,我的问题源于我交换了光标。如果您不这样做,您可能永远不会注意到任何问题,但我认为最好了解它们。

于 2015-04-18T16:03:36.930 回答