findViewById方法探究

Android findViewById及替代方案大全 自打学习Android开发以来,findViewById就是我使用最频繁的函数之一。findViewById可为灵活至极,但是又让人爱恨交加。那findViewById究竟有哪些优缺点,他又有哪些替代方案呢?今天就来做一个总结 findViewById findViewById的原理 findViewById的原理非常简单,我们都知道Android中的View结构是一个树形结构,findViewById就是自树的根节点,依次遍历其子节点,知道找到目标的id。 findViewById的优点 还是先夸夸fi 阅读详情

        配置布局的xml文件时,有时会给View配置id,而在Activity中寻找到该View的方法就是通过该id号来找到该View的。具体调用的方法就是findViewById。

        这个findViewById方法顾名思义,就是根据id来找到View,而Android内部的实现,也同样遵循了这个原则。具体见下面的源代码分析。

        Activity中的findViewById方法执行流程如下:Activity.findViewById() >> Window.findViewById() >> DecorView.findViewById()。在这个流程中,没有干具体的事情,只是一步步调用到了DecorView的findViewById方法。


Activity.java

// findViewById方法
public View findViewById(@IdRes int id) {
    return getWindow().findViewById(id);
}
 
// getWindow方法,获取到activity对应的window对象
public Window getWindow() {
    return mWindow;
}

PhoneWindow.java

public View findViewById(@IdRes int id) {
    return getDecorView().findViewById(id);
}
 
// 获取到root View,而该root View继承自FrameLayout
public final View getDecorView() {
    if (mDecor == null) {
        installDecor();
    }
    return mDecor;
}

        DecorView继承自FrameLayout,是根View,可以理解为整个View树的起始点,联想测量、布局、绘制以及事件分发消费,那么findViewById也是这样的处理思路,概括来说,Activity的findViewById方法就是从根View自身开始,遍历自身子View,尝试查找View树中是否存在mID等于id的View或ViewGroup。说是尝试,因为也有可能找不到。

        从Root View开始,就是要正式进入到寻找mID为id的View或ViewGroup过程了。具体执行流程参考如下:View.findViewById() >> ViewGroup.findViewTraversal() >> View.findViewById() >> ViewGroup.findViewTraversal() >> View.findViewById() >> View.findViewTraversal()。


View.java

// 根据给定的id找指定的View(ViewGroup不能重写)
public final View findViewById(@IdRes int id) {
    if (id < 0) { // id不能为负数
        return null;
    }
    // 调用findViewTraversal方法
    return findViewTraversal(id);
}
 
// 通过遍历找到View
protected View findViewTraversal(@IdRes int id) {
    if (id == mID) {
        // 如果id号与View的mID一致,则返回View自身
        return this;
    }
    // 否则返回null
    return null;
}


ViewGroup.java

// 重写了View的findViewTraversal方法,通过遍历找到View
protected View findViewTraversal(@IdRes int id) {
    // 如果id号恰好与viewgroup的mID一致,就返回ViewGroup自身
    if (id == mID) {
        return this;
    }
 
    final View[] where = mChildren;
    final int len = mChildrenCount;
 
    // 遍历子View,
    for (int i = 0; i < len; i++) {
        View v = where[i];
 
        if ((v.mPrivateFlags & PFLAG_IS_ROOT_NAMESPACE) == 0) {
            // ①如果该子View是ViewGroup,就继续先判断自身的mID是否匹配
            //   如果不匹配,再遍历该ViewGroup的子View,继续判断是否匹配,依次循环下去
            // ②如果该子View是View,就直接判断View的mID是否匹配
            v = v.findViewById(id);
 
            if (v != null) {
                // 如果匹配成功,则返回找到的这个View对象
                return v;
            }
        }
    }
    // 所有子View及其ViewGroup自身的mID都不能匹配上id号,那么就找不到该id号匹配的View了,返回null
    return null;
}

        由于View的findViewById是final,所以ViewGroup不可以重写。而我们可以注意到在View的findViewById中对id是否为负数进行了判断,那么问题来了,为什么不在Activity中判断呢?每次都判断不是浪费时间吗?
        因为不仅Activity会调用findViewById方法,当用LayoutInflater导入一个自定义的布局时,也有需要根据布局中定义的id来找到对应的View,从而进行处理。此时,也要进行判断id是否为负数。


        总结如下,Activity的findViewById最终还是会调用到View的findViewById方法;Activity的findViewById方法就是从根View自身开始,遍历自身子View,尝试查找View树中是否存在mID等于id的View或ViewGroup;View的findViewById方法就是从该View自身开始,遍历自身子View,尝试查找该View的树中是否存在mID等于id的View或ViewGroup。





Adapter简化写法以及findViewById()方法的优化 首先写个ViewHolder: public class ViewHolder { private View mConvertView; private Activity mActivity; private SparseArray mViewArray; // 包含了View引用的SparseArray public ViewHolder(View 阅读详情

相关推荐

手把手教你排查I2C通信故障:当上拉电阻配置不当会发生什么?

本文深入解析I2C通信中上拉电阻配置不当导致的常见故障,包括波形畸变和通信失败现象。通过示波器波形分析和系统化解决方案,帮助工程师快速诊断和优化I2C总线性能,特别适用于嵌入式系统和智能设备开发场景。

weixin_33725722的博客 340

[android]深入理解findViewById原理

用的太多了,但是不知道原理。Xutils里面舍弃了findViewById改用注解,当时也很不理解。一步步了解后,发现,相比注解的方式加载控件,findViewById的效率是很低的。 点进去看源码进入Activity.class类里的方法: 发现这个返回的是getWindow()的findViewById方法,这个getWindow()是什么? Activity.class

努力奋斗 2万+

Visio 2013安装遇阻?手把手教你搞定注册表权限错误1402(附64位系统特殊处理)

本文详细解析了Visio 2013安装过程中常见的注册表权限错误1402问题,特别是在64位系统下的特殊处理方法。通过分步指导如何修改注册表权限、处理Wow6432Node分支以及使用高级工具如subinacl,帮助用户顺利完成安装并避免常见连带问题。

t8u9v0w1x的博客 540

findViewById原理

findViewById原理 前言 从表面上来看,findViewById就是根据R文件中的id值查询到相应的View,然后返回。  那么问题来了,这些View是在find的时候才被实例化还是父View实例化好的时候就已经实例化好了,findViewById只是从数据源中取出来。  答案是在父类被实例化好的时候就已经完成了子类的实例化,并且形成了一个DOM树。这个DOM数其

zjy519893509的专栏 1万+

华为2288H-V5服务器做raid的详细步骤

操作步骤 服务器启动界面 按del键进入设置输入密码,2288H-v5默认密码是Admin@9000 移动光标选择device manager 驱动管理选择configurationutility 配置管理 选择main menu 主菜单 选择第一个 configuration management 配置管理 选择create virtual driver 创建虚拟驱动选择select RAID level 选择RAID等级选择level-5 选择select drivers 选择驱......

weixin_46041124的博客 1万+

机器学习入门指南:Jupyter Notebook实战

对于机器学习工程师而言,他们更擅长的是算法、模型、数据探索的工作,而对于工程化的能力则并不是其擅长的工作。Jupyter Notebook生成PMML文件1​​​​​​​。Jupyter Notebook生成PMML文件2​​​​​​​。PySpark Notebook建模 -折线图​​​​​​​。TensorFlowNotebook建模​​​​​​​。R Notebook建模 - 散点图​​​​​​​。PySpark Notebook建模​​​​​​​。R Notebook获取训练数据集​​​​​​​。

datacreating的博客 1973

讲解findViewById的用法&是做什么的

安卓编程的定位函数,主要是引用.R文件里的引用名。一般在R.java文件里系统会自动帮你给出你在XML里定义的ID或者Layout里面的名称,例如:Button button=(Button)findViewById(R.id.button01);这样就引用了XML(res里的布局文件)文件里面的button,使得在写.java的按钮时能与XML里的一致。

ProveYourself的博客 4万+

【论文阅读1】机理引导的残差学习用于电池全生命周期状态监测 | Nature Communications

本文提出了一种机理引导的残差学习框架,用于提升电池全生命周期内荷电状态(SOC)和健康状态(SOH)的监测精度。该方法融合等效电路模型的先验知识与机器学习,设计了修正模型和补偿模型两种通用框架。实验验证表明,该方法在三种不同类型电池数据集上均表现出色,SOC和SOH估计误差较传统方法降低50%以上,且在未见工况下仍保持良好外推能力。模型具有强鲁棒性,在减少训练数据量和降低采样频率时性能稳定,并兼具物理可解释性。该框架无需离线测试和运行中校准,为电池安全监测提供了有效解决方案。

qq_21843433的博客 613

安卓findViewById 的优化方案:ViewBinding与ButterKnife(一)

安卓findViewById 的优化方案:ViewBinding与ButterKnife(一)

u013083465的专栏 1929

2026年数字IC设计华为笔试带答案解析

这篇文章是一份数字IC设计工程师笔试的试卷结构和部分题目解析。试卷包含单选题31题(每题2分)、多选题10题(每题4分)和简答/编程题4题(每题7分),总分130分,考试时长120分钟。 摘要重点: 试卷涵盖数字IC设计的关键知识点,包括Verilog语法、时序逻辑、状态机设计、跨时钟域处理等; 题目解析详细说明了各选项的正确性,如非阻塞赋值特性(D错误)、功耗影响因素(C与组合逻辑级数弱相关)等; 包含实际工程问题,如DDR4接口电平(SSTL-1.2)、卡诺图变量排序(格雷码)等; 部分题目考察基础概念

Open 368

路径规划 | 详解混合A*算法Hybrid A*(附ROS C++/Python/Matlab仿真)

Hybrid A*算法通过结合连续状态空间搜索、运动约束考虑和轨迹优化等技术,弥补了普通A*算法在高维连续空间和的不足,提高了路径规划的效率和鲁棒性,广泛应用于车规级路径规划。本文详细图解Hybrid A*算法的原理——启发式、维诺耗散项、节点扩展法则等,并给出ROS C++、python、matlab三种语言的仿真实现加深理解

FRIGIDWINTER的博客 1万+

通过对inflate与 findViewById 方法的探究深度了解一下Android

目前为止,很多大牛已经纷纷发表了对inflater.inflate方法与findViewById方法的见解。从概要上,小编总结了一下讲得比较靠谱的说法,之后会针对这方面进一步做一下测试探究,帮助Android新手更进一步了解一下我们正在一个什么样的平台上怎样便利地开发着一款软件。 ==========================================================

小轩腾空的专栏 895

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

android--android studio findViewById 出现 Ambiguous method call. Both

上面这张图是盗的图,因为我的问题已经解决了,,没截图。 问题: 如图所示,findViewById()方法在Activity中和AppCompatActivity中都存在,所以编译器不知道你用的哪一个。 解决: 我参考了若干篇抄来抄去的博客文章,最后没找到解决办法。最后将API升级到26,错误就消失了。 原理: 我也不知道。 > 哪位大佬知道这是怎么回事,万望在评论区告诉在下,再次先行谢过...

ihan.的博客 942

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

Android中通过注解代替findViewById方法

这篇文章主要讲解注解实现findViewById的功能,首先我们来熟悉一下在java中怎么定义一个注解和解析一个注解 注解的概念是在jdk5.0中提出来的,在java.lang的包中已经定义了三个注解:Override,Deprecated,SuppressWarnings Override相信大家非常熟悉,就是表明这个方法是改写了父类的方法 Deprecated表示在新版本的 jdk中已经

Android学习之旅 5636

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

inflate 方法与 findViewById方法的区别

不同点:layoutinflater是用来找res/layout/下的xml布局文件,并且实例化;而findviewbyid()是找xml布局文件下的具体widget控件(如button、textview等)。 具体作用: 1、对于一个没有被载入或者想要动态载入的界面,都需要使用layoutinflater.inflate()来载入; 2、对于一个已经载入的界面,就可以使用act

amao的博客 542

关于在findViewById()方法时遇到的一些问题

最近需要做一个关于色卡的App,需要用到LayoutInflater来实现标签动态切换View界面,但是发现在使用过程中App突然会闪退, 闪退目前已解决。 先看下关于findViewById()的详细介绍:findViewById()是找具体某一个xml下的具体 widget控件(如:Button,TextView等) 我的闪退原因:我将findViewById()用在了还没有动态加载我要查找...

Jason的学习笔记 1287

关于Android 开发中 Java方法findViewById的使用

在实际开发中,当遇到有很多UI组件时,各个组件会通过andriod:id 属性给每个组件设置一个唯一的标识。当需要在代码中访问指定的组件时(例如设置单击事件),就可以通过id值,利用方法findViewById(R.id.id值)来访问。 例如: public class MainActivity extends AppCompatActivity { Button bn ; EditText s...

hdfinder的博客 1万+

kotlin代替findViewById的方法

在安卓项目使用了Kotlin之后,发现Kotlin一个相当强大的地方,可以不用findViewById,引入布局,直接使用控件 方式一:使用kotlin插件自动生成 引入kotlin扩展插件 apply plugin: ‘kotlin-android-extensions’ 引入kotlin自动生成的相关布局文件 import kotlinx.android.synthetic...

king的专栏 6696

Fragment中使用findViewById

如果你为Fragment在XML文件中创建了什么控件,但findViewById方法却只能被用在Activity类中,所以,有没有办法在Fragment中使用它呢 使用getView()方法就OK了,因为这个方法最终会返回当前fragment的根视图。 Button btn = (Button) getView().findViewById(R.id.btn); 但是在此之前要使用onCreateView来创建视图。 @Override public View onCreateView(L

半甜去冰的博客 2386

findViewById返回空指针的解决方法

用Toast来输出一SQL语句,结果当我调用TextView tv = (TextView) findViewById(R.id.toast_tv);时, 总是返回空指针。 找了例子程序, 通过仔细比对, 发现正确的语句应该是TextView tv = (TextView) view.findViewById(R.id.toast_tv);   此处的view是通过一个LayoutInf

cc_lq的专栏 1811

Android开发中简化findViewById的几种方法

这几天查资料,DataBind暂且不谈,简化findViewById方法主要有三种:1、注解;2、另类写法;3、已有框架。 1、注解,这是通过反射的原理,自已写注解方法,可以参考该网址:http://www.cnblogs.com/Fndroid/p/5354644.html。 2、另类写法,使用泛型可以简化强制转化的步骤,该方法在BaseActivity中使用findViewById,参考网

木偶16的博客 2417

findViewById 原理

有人问了 findViewById 到底做了什么事情,有点懵逼,在此深入研究以下 findViewById 流程图 1. Activity 的 findViewById 点进去看源码进入 Activity.class 类里的方法: /** * Finds a view that was identified by the id attribute from the XML t...

怪咖先森的博客 2297

dialog也有findViewById方法

dialog也有findViewById方法,由此可以通过这个方法,来通过Id获得包含在这个Dialog的layout文件中的控件。

2969

Android-findViewById()方法分析

findViewById()方法分析首先,看我们在Activity中调用的findViewById方法:@Nullable public View findViewById(@IdRes int id) { return getWindow().findViewById(); }调用了Window的findViewById()方法,获取结果。那么下面,我们就来看看Window

Abe的学习之路 7519

inflate和findViewById方法对比

Inflate()作用就是将xml定义的一个布局找出来,但仅仅是找出来而且隐藏的,没有找到的同时并显示功能。最近做的一个项目就是这一点让我迷茫了好几天。 android上还有一个与Inflate()类似功能的方法叫findViewById(),二者有时均可使用,但也有区别 区别在于: 如果你的Activity里用到别的layout,比如对话框layout,你还要设置这个lay

白马笑西风的专栏 1327
上一篇: Android自定义View训练【2】
下一篇: Activity中使用Dialog的方式
Sun_Jingjing
博客等级 码龄10年 1粉丝 23原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值