解决方法是在 clear()
中将mRoot字段置空,或者将 ViewLocationHolder.mRoot
字段设置为弱引用。
但是,我们修改不了ViewGroup的源码,它是属于framework
层的= = ,他是来自于framework层的Bug,所以我们只能任由这个泄漏出现…
=========================================================================
这里不得不产生了更多的问号。
(1)为什么是只有Andorid P有这个玩意?
(2)我用到ViewGroup的地方这么多,那是不是只要在Android P上,我随时随地都可能出现这个Bug?
对于这样的问题,我不得不再往下深入代码了= =
首先,我们得先找到ViewLocationHolder
会在什么时候拿出来用,它的入口方法是 ViewLocationHolder.obtain()
,我们要看看是谁调用了obtain:
// ViewGroup.java
/**
-
Pooled class that orderes the children of a ViewGroup from start
-
to end based on how they are laid out and the layout direction.
*/
static class ChildListForAccessibility {
private static final int MAX_POOL_SIZE = 32;
private static final SynchronizedPool sPool =
new SynchronizedPool(MAX_POOL_SIZE);
private final ArrayList mChildren = new ArrayList();
private final ArrayList mHolders = new ArrayList(); // 1
public static ChildListForAccessibility obtain(ViewGroup parent, boolean sort) {
ChildListForAccessibility list = sPool.acquire(); // 2
if (list == null) {
list = new ChildListForAccessibility();
}
list.init(parent, sort); // 3
return list;
}
private void init(ViewGroup parent, boolean sort) {
ArrayList children = mChildren; // 4
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
View child = parent.getChildAt(i);
children.add(child); // 5
}
if (sort) { // 6
ArrayList holders = mHolders; // 7
for (int i = 0; i < childCount; i++) {
View child = children.get(i);
ViewLocationHolder holder = ViewLocationHolder.obtain(parent, child); // 8
holders.add(holder);
}
sort(holders); // 9
for (int i = 0; i < childCount; i++) { // 10
ViewLocationHolder holder = holders.get(i);
children.set(i, holder.mView);
holder.recycle(); // 11
}
holders.clear();
}
}
…
}
这里又出现了了一个ViewGroup的静态内部类:ChildListForAccessibility
,从英文注释中可以看出,它的作用就是管理所有的ViewLocationHolder
,而且它同样被放在一个池子中。在注释1中,它持有了一个ViewLocationHolder类型的list。来解析下这个源代码:
注释2、3:从池子中取出一个空的ChildListForAccessibility
,然后调用其 init()
注释4、5:调用ViewGroup.getChildCount
和ViewGroup.getChildAt
,拿到所有的子View存放到 children对象中。
注释6:判断是否需要对这些子View进行排序,如果要,则进入到if语句中去。
注释7:创建 ViewLocationHolder类型的list
注释8:为注释5中的 children对象里面的每一个子View创建一个 ViewLocationHolder
,并放入到注释7的list中
注释9:给这个list排序。排序后,里面所有的子View都有了顺序。
注释10:遍历这个排序的list,重新将排好序的list的子View放到 children对象中去。
注释11:注释7的list已经没用了,所以调用每个 ViewLocationHolder.recycler()
,这个方法就会调用上节中的 clear()
释放资源。
这个类的作用是对ViewGroup的所有子类进行排序,所以我们要找到从哪里进行排序的,因为ChildListForAccessibility.obtain()
是入口方法,所以我们要找到使用到这个方法的地方,我发现有两处ViewGroup的方法调用了它,他们分别是
ViewGroup.addChildrenForAccessibility
将可以访问(即可以有焦点)的子View添加到 outChildren
这个对象中
ViewGroup.dispatchPopulateAccessibilityEventInternal
用来分发焦点事件,遍历所有排序后的子View,如果某个子View获取焦点,则退出循环。
这个方法是处理一个ViewGroup里面可以获得焦点的子View的一类方法。也就是说,无论是哪个版本,都可以执行这些方法。
下面是截取的Android7.0的ViewGroup的 ViewLocationHolder类:
下面是截取自Android8.0的代码:
下面是Android10.0的代码:
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
总结:
各行各样都会淘汰一些能力差的,不仅仅是IT这个行业,所以,不要被程序猿是吃青春饭等等这类话题所吓倒,也不要觉得,找到一份工作,就享受安逸的生活,你在安逸的同时,别人正在奋力的向前跑,这样与别人的差距也就会越来越遥远,加油,希望,我们每一个人,成为更好的自己。
-
BAT大厂面试题、独家面试工具包,
-
资料包括 数据结构、Kotlin、计算机网络、Framework源码、数据结构与算法、小程序、NDK、Flutter,
,这样与别人的差距也就会越来越遥远,加油,希望,我们每一个人,成为更好的自己。
-
BAT大厂面试题、独家面试工具包,
-
资料包括 数据结构、Kotlin、计算机网络、Framework源码、数据结构与算法、小程序、NDK、Flutter,
[外链图片转存中…(img-p4MofNZV-1711826975281)]
[外链图片转存中…(img-57bPXgC1-1711826975282)]