关于ViewGroup$ViewLocationHolder$mRoot的内存泄漏,Android程序员校招蚂蚁金服

解决方法是在 clear()中将mRoot字段置空,或者将 ViewLocationHolder.mRoot字段设置为弱引用

但是,我们修改不了ViewGroup的源码,它是属于framework层的= = ,他是来自于framework层的Bug,所以我们只能任由这个泄漏出现…

2. 源码反推

=========================================================================

这里不得不产生了更多的问号。

(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.getChildCountViewGroup.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移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
img

总结:

各行各样都会淘汰一些能力差的,不仅仅是IT这个行业,所以,不要被程序猿是吃青春饭等等这类话题所吓倒,也不要觉得,找到一份工作,就享受安逸的生活,你在安逸的同时,别人正在奋力的向前跑,这样与别人的差距也就会越来越遥远,加油,希望,我们每一个人,成为更好的自己。

  • BAT大厂面试题、独家面试工具包,

  • 资料包括 数据结构、Kotlin、计算机网络、Framework源码、数据结构与算法、小程序、NDK、Flutter,


,这样与别人的差距也就会越来越遥远,加油,希望,我们每一个人,成为更好的自己。

  • BAT大厂面试题、独家面试工具包,

  • 资料包括 数据结构、Kotlin、计算机网络、Framework源码、数据结构与算法、小程序、NDK、Flutter,

    [外链图片转存中…(img-p4MofNZV-1711826975281)]
    [外链图片转存中…(img-57bPXgC1-1711826975282)]

本文已被CODING开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》收录

  • 9
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值