Android 获取控件id的三种方式

本文介绍了在Android中获取控件id的三种方法:findViewbyid、注解方式(如ButterKnife)和反射。通过源码分析,详细解释了findViewbyid的底层实现,指出其通过window找到管理Activity UI界面的DecorView。此外,对比了注解方式的便利性,并提及反射的应用。
摘要由CSDN通过智能技术生成

前言:

获取控件是入门的基本的,相信这个不用说就知道怎么得到资源文件中的控件id

  1. 有findViewbyid
  2. 有注解方式
  3. 反射的方式

通过findViewbyid获取

  • 原理

  • 我们点击进入Activity.java类中看源码,通过源码我们发现返回的是getWindow.findViewById,这个window是什么呢?我们再次点击进去看看,

···
/**
* Finds a view that was identified by the id attribute from the XML that
* was processed in {@link #onCreate}.
*
* @return The view if found or null otherwise.
*/
@Nullable
public View findViewById(@IdRes int id) {
return getWindow().findViewById(id);
}
···

  • 进入window发现是window,window是一个抽象类,window不能实现UI界面,那么这个getDecorView()返回的是一个VIew来管理Activity UI界面的
    /**
     * Finds a view that was identified by the id attribute from the XML that
     * was processed in {@link android.app.Activity#onCreate}.  This will
     * implicitly call {@link #getDecorView} for you, with all of the
     * associated side-effects.
     *
     * @return The view if found or null otherwise.
     */
    @Nullable
    public View findViewById(@IdRes int id) {
        return getDecorView().findViewById(id);
    }
  •  
//通过findViewbyid获取布局文件中的id
TextView tv=(TextView)findViewbyid(R.id.text);//

接下来我们看看注解方式
通过在线引用butterknife jar包就行了
//只需要在每个ID上设置对应的注解即可
@BindView(R.id.img1)
private ImageView img1;`对没有看错就是这么简单

 再来看看反射获取的
/**
     * 使用java反射机制
     * 设置Activity不用findViewbyid
     */
    private void smartInject() {
        try {
            Class<? extends Activity> clz = getClass();

            while (clz != BaseActivity.class) {
                Field[] fs = clz.getDeclaredFields();
                Resources res = getResources();
                String packageName = getPackageName();
                for (Field field : fs) {
                    if (!View.class.isAssignableFrom(field.getType())) {
                        continue;
                    }
                    int viewId = res.getIdentifier(field.getName(), "id", packageName);
                    if (viewId == 0)
                        continue;
                    field.setAccessible(true);
                    try {
                        View v = findViewById(viewId);
                        field.set(this, v);
                        Class<?> c = field.getType();
                        Method m = c.getMethod("setOnClickListener", View.OnClickListener.class);
                        m.invoke(v, this);
                    } catch (Throwable e) {
                    }
                    field.setAccessible(false);

                }
                clz = (Class<? extends Activity>) clz.getSuperclass();
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    //这是我项目中封装在BaseActivity的,可以直接在BaseActivity中放在onCreate就行了,具体的看自己BaseActivity怎么封装了0.0

那么在Activity或者fragment中怎么使用的呢,很简单、个人觉得比findViewbyid和注解bindView方便多了,只需要跟布局文件中的id相同就行了,有点类似kotlin那样,不过还是没有kotlin Android那样简洁方便
end

作者:枫叶冒险岛
链接:https://www.jianshu.com/p/c18beeff391c
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值