通过实现ViewBinding,学习自定义插件及JavaPoet的使用

一、概述

这篇文章是为了了解viewBinding是如何实现的,我很好奇为什么我们在项目的module的build.gradle中添加了如下代码

viewBinding{
    enable true
}

在make项目后就能自动生成ActivityMainBinding这些类的呢?

而我们为什么通过binding就能找到对应的控件的呢?

网上的博客中大部分都是只解释了,自动生成的ActivityMainBinding类中替我们做了findViewById所以我们可以通过binding找的对应的控件,但是这个类是怎么生成的呢?

了解过JavaPoet的同学可能知道,通过javaPoet可以用代码生成类,学过注解的同学可能会想通过注解+JavaPoet就能实现这个功能了,但是viewBinding并没有使用注解啊。

通过学习我了解到了,viewBinding的实现流程如下

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RnIzamWu-1636121567401)(https://upload-images.jianshu.io/upload_images/27208762-2db6ca56b51b7090.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)]

由图可知,viewBinding是在make项目后才执行生成文件的代码,再加上build.gradle中的enable配置,所以联想到了gradle插件。

总结:所以整体流程就是由gradle插件实现通过viewBinding的enable配置决定是否启用viewBinding的代码生成,启用的话则使用JavaPoet来实现自动生成内部实现了findViewById和控件赋值的Java类。

二、实现viewBinding

1.使用JavaPoet生成Java文件

我们生成的Java类全貌如下:

public class ActivityMainBinding {
  public final ConstraintLayout rootView;

  public final TextView text;

  private ActivityMainBinding(ConstraintLayout rootView, TextView text) {
    this.rootView = rootView;
    this.text = text;
  }

  public ConstraintLayout getRoot() {
    return rootView;
  }

  public static ActivityMainBinding setContentView(Activity activity, int layoutId) {
    View decorView = activity.getWindow().getDecorView();
    ViewGroup contentView = decorView.findViewById(android.R.id.content);
    ConstraintLayout root = (ConstraintLayout) LayoutInflater.from(activity).inflate(layoutId, contentView, false);
    activity.setContentView(root);
    return bind(root);
  }

  public static ActivityMainBinding bind(ConstraintLayout rootView) {
    String missingId;
    TextView text = rootView.findViewById(R.id.text);
    if(text == null) {
     throw new NullPointerException("Missing required view with ID:"+text);
    }
    return new ActivityMainBinding(rootView,text);
  }
}

我个人使用JavaPoet生成Java类的心得就是你先写好需要的Java类,然后根据这个模版再去使用JavaPoet生成,避免你写到一半忘记自己需要什么方法,以及参数,返回值类型的问题。

(1) 遍历module下的res/layout目录,找到所有的xml文件,并且通过xml解析获取xml中定义了id的控件id和类型;

示例:

//拼接layout目录path
String layoutPath = project.getProjectDir().getAbsolutePath()+
        File.separator + "src" + File.separator + "main" +
        File.separator +"res" + File.separator +"layout";
File layoutDirFile = new File(layoutPath);
System.out.println("layoutPath: "+layoutPath);
if (layoutDirFile.exists()) {//layout目录存在

    File[] listFiles = layoutDirFile.listFiles();
    if (listFiles != null && listFiles.length > 0) {//layout目录下有文件

        for (File file : listFiles) {//遍历目录下的文件
            if (file.isFile() && file.getName().endsWith(".xml")) {//找到xml格式的文件
                // 是文件且是xml文件
                String fileName = file.getName().replace(".xml", "");
                String bindingClassName;
                if (fileName.contains("_")) {
                    // 按下划线切割
                    StringBuilder tempClassName = new StringBuilder();
                    for (String s : fileName.split("_")) {
                        tempClassName.append(
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值