Android中多次调用findViewById与成员变量存View哪种方案更优
自定义View视图访问方案选型结论
优先选择将视图控件保存为成员变量的实现方案,综合收益远高于每次调用findViewById获取对象的方案。
两种方案的成本对比
- 成员变量方案的内存开销几乎可以忽略
单个View对象的引用在Android Runtime中仅占4~8字节,就算布局内有二三十个TextView、Button控件,全部存为成员变量的总内存开销也不到1KB,远小于一张普通位图、甚至一个普通业务对象的内存占用。且这些成员变量的生命周期和自定义View/宿主Activity完全绑定,页面销毁、View移除时引用会随宿主一起被回收,根本不会造成额外的内存泄漏或者内存压力。 - 每次调用
findViewById的性能开销是实打实的冗余消耗
原生findViewById没有内置结果缓存,每次调用都会从当前根节点出发遍历整个视图树,通过ID匹配查找目标控件。如果你的布局层级较深、控件数量较多,单次查找就可能耗时1~5毫秒;如果单次视图更新要查找多个控件、生命周期内更新次数超过2次,累计耗时很容易突破主线程单帧16ms(60帧场景)的安全阈值,在列表滚动、属性动画这类对帧率敏感的场景下,很容易直接造成可见的掉帧卡顿。
实际开发的选型建议
- 常规场景直接在布局加载完成(自定义View的
onFinishInflate、Activity的onCreate里inflate结束)时,统一做一次视图查找,把需要操作的控件全部赋值给成员变量,后续访问直接调用即可,这是Android原生开发的标准实践,没有任何性能或者内存隐患。 - 嫌手动写
findViewById麻烦可以直接用官方的ViewBinding框架,本质也是编译期帮你生成好视图成员变量的绑定代码,比自己手写更不容易出错。 - 真要极致抠内存,完全没必要在视图查找上做文章,真遇到极少用到的控件,可以在控件确认不再使用(比如自定义View触发
onDetachedFromWindow、页面销毁)时把成员变量置空就行,没必要每次用的时候重复遍历视图树。 - 别信什么"findViewById现在很快"的说法,我之前排查过列表滚动掉帧的问题,最后定位到的原因就是item的自定义View每次绑定数据都重新调用
findViewById找控件,改成成员变量缓存之后帧率直接从42帧回升到稳定60帧,省的那点百字节级别的内存,连一张应用内小图标内存占用的千分之一都不到,完全是捡芝麻丢西瓜的选择。
内容的提问来源于stack exchange,提问作者Android_Learner
相关产品推荐
相关产品推荐

