ViewHolder不是内部类 [英] ViewHolder not as a inner class

查看:119
本文介绍了ViewHolder不是内部类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

RecyclerView.ViewHolder不能用作内部类吗? 这样做有什么问题吗?

我已经搜索过了,但是还没有找到任何文档!

解决方案

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

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

但是,就我而言,我遇到了与内存无关的实际问题.我的适配器有一个选择模式",其保持位置到数据映射和视图保持器将使用该数据时所显示的项目(例如像它,当选择模型表示在位置17上的项目被选择,当它是在屏幕上绘制时,其字体颜色会更改)以为用户标记.它是通过仅从适配器访问选择模型字段来实现的,这在Java中意味着它使用对封闭的适配器实例的隐式引用,然后访问其字段.现在,在swapAdapter之后,保留的ViewHolders仍在使用适配器的选择模型,并且UI被破坏了,因为某些项目将显示为已选择状态,而在新模型中则未显示./p>

从本质上讲,对于这样的非静态内部类持有者来说,它们的生存期超出了创建它们的适配器并被另一个人使用,从而使他们真的忘记了旧适配器而使用了新适配器,因为无法清除该隐式引用

对此有很多解决方案,其中一种方法是将ViewHolder成为静态嵌套类,并在绑定时将其明确引用适配器,并在取消绑定时将其为null.我一直在为视图持有者使用顶级类,并带有对适配器的显式引用,我认为这正是您所要的.请注意,通常情况下,持有人根本不需要任何引用其适配器的信息,因此您可能根本不需要设置适配器.

当然,我的问题源于我更换了光标的事实.如果您不这样做,则可能永远不会注意到任何问题,但我认为最好是意识到这些问题.

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!

解决方案

Actually, I think a ViewHolder should either be a static nested class (mind the static!) or a top-level class (which actually will be no different, just the class name will contains the outer class name followed by a $ and then the inner class name).

Why do I think so? When the ViewHolder is a non-static inner class of the adapter, it keeps a reference to the adapter. Now, when you call RecyclerView.swapAdapter(newAdapter, false) (or was it true? I don't remember), the new adapter will use the ViewHolders created previously by the old one. As it is impossible to null/clear such an implicit reference in these holders, this reference to the first adapter has leaked and cannot be garbage collected. This is bad enough.

But, in my case, I had real issues not related to memory. 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 drawn on screen, its font color would change) to mark it for the user. It did it by just accessing the selection model field from the adapter, which in Java means it uses the implicit reference to the enclosing adapter instance and than accesses its field. Now, after swapAdapter, the preserved ViewHolders were still using the selection model of the old adapter, and the UI was broken, as some items would show up as selected whereas in the new model they were not.

Essentially, it is impossible for such non-static inner class holders who outlive the adapter that created them and are used by another one to really forget the old and use the new adapter, as there is no way to clear that implicit reference.

There are many solutions to this, one of which is for the ViewHolder to be a static nested class, and just give it a reference to the adapter explicitly when it binds, and null it when it unbinds. I have been using a top-level classes for my view holders with explicit references to the adapter, which I think it what you are asking about. Mind that very often the holders don't need any reference to their adapter at all so you might not need to set the adapter at all.

Of course, my issue stemmed from the fact that I swapped the cursor; if you don't do it, you probably won't ever notice any problems, but I think it is best to be aware of them.

这篇关于ViewHolder不是内部类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆