• 学学Viewbinding


    Viewbinding

    1.环境需求

    环境上,需要Android Studio 3.6 Canary 11+

    同样的Gradle也需要升级(这年头都4.0了,应该没有还在用低版本的了吧...)

    2.配置viewbinding

    gradle 版本在 3.6 - 3.9 以上的:

    app文件夹 下的 build.grale 里面添加

    android {
        ...
        viewBinding {
            enabled = true
        }
    }
        
    

    如果你的 gradle 是 4.0+ ,那么需要改一下写法

    android {
        ...
        buildFeatures {
            viewBinding true
        }
    }
    

    否则可能会报一个warnning,虽然不改并大概率不影响使用,但作为一个优秀程序员凑合了事可不是什么好习惯

    DSL element 'android.viewBinding.enabled' is obsolete and has been replaced with 'android.buildFeatures.viewBinding'.
    

    3.用法

    原理

    Viewbinding 的原理就是根据 idbuild 文件夹下生成对应的 java类,然后在 java类 里面自动帮你 findViewById(对,没错,原理还是findViewById,并没什么新鲜的),布局文件里面的子控件,就对应 java类 里面的 field(成员变量)
    然后你就可以调用 java 类来操作控件

    对应生成的java类文件,名字就是 删除下划线 再加 Binding

    例如:activity_main.xml ==> ActivityMainBinding.java

    某些布局不用viewbinding

    如果你不希望某个布局(layout)被 Viewbinding 所“控制”(生成java类文件),那就添加 tools:viewBindingIgnore="true"

    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:viewBindingIgnore="true">
        ...
    
    </LinearLayout>
    

    Tip:可能这里你有一个骚操作——我布局采用 Viewbinding 但,某个控件不用,我自己 findViewById ,想法不错,但是Google不同意,在子布局或控件里加 tools:viewBindingIgnore="true" 是无效的

    实战

    activity_main.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
    
    </LinearLayout>
    

    MainActivity.java

    public class MainActivity extends AppCompatActivity {
    
        private ActivityMainBinding mMainBinding;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            mMainBinding = ActivityMainBinding.inflate(getLayoutInflater());
            setContentView(mMainBinding.getRoot());
        }
    }
    

    这个代码用法非常简单,就是声明一个Viewbinding帮我们生成的ActivityMainBinding,然后用inflate加载他,getRoot就是获得他的根布局,跟R.layout.activity_main是一个东西。

    inflate我多说两句

    inflate 跟Layoutinflate的inflate不是一个方法,但用法类似。
    作用就是加载布局(初始化ViewBinding)

    源码是

      @NonNull
      public static ActivityMainBinding inflate(@NonNull LayoutInflater inflater) {
        return inflate(inflater, null, false);
      }
    
      @NonNull
      public static ActivityMainBinding inflate(@NonNull LayoutInflater inflater, @Nullable ViewGroup parent, boolean attachToParent) {
        View root = inflater.inflate(R.layout.activity_main, parent, false);
        if (attachToParent) {
          parent.addView(root);
        }
        return bind(root);
      }
    

    一共两个重载,还是很好理解的,用过LayoutInflate的肯定一看就明白

    1. 如果parent为null,attachToParent将失去作用,设置任何值都没有意义。

    2. 如果parent不为null,attachToParent设为true,则会给加载的布局文件的指定一个父布局,即parent。

    3. 如果parent不为null,attachToParent设为false,则会将布局文件最外层的所有layout属性进行设置,当该view被添加到父view当中时,这些layout属性会自动生效。

    4. 在不设置attachToParent参数的情况下,如果parent不为null,attachToParent参数默认为true。

    加载控件(套娃模式)

    我们先在 activity_main.xml 添加一个textView

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
    
        <TextView
            android:id="@+id/text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="#FF8686"
            android:text="111"**
            android:textSize="40sp" />
    
    </LinearLayout>
    

    再在 MainActivity 里面编写调用代码

    public class MainActivity extends AppCompatActivity {
    
        private ActivityMainBinding mMainBinding;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            mMainBinding = ActivityMainBinding.inflate(getLayoutInflater());
            setContentView(mMainBinding.getRoot());
    
            mMainBinding.text.setText("dududududu");
        }
    }
    

    调用很简单,直接 mMainBinding.text.settext就可以了,这跟我们之前说的将控件 生成为java类 的成员变量也十分符合。

    可我为什么称它为套娃模式呢???我们再尝试添加一个 嵌套一个layout试试

    新建一个布局叫:layout_include.xml

    <?xml version="1.0" encoding="utf-8"?>
    <FrameLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
    
        <TextView
            android:id="@+id/include_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="50sp" />
    
    </FrameLayout>
    

    再修改 activity_main.xml 的内容,将layout_include加载进去

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
        ...>
    
        <TextView
         ... />
    
        <include 
            android:id="@+id/include"
            layout="@layout/layout_include" />
    </LinearLayout>
    

    那么我们怎么调用 layout_include.xml 里面的 textview 呢???

    我们修改MainActivity里面的代码

    public class MainActivity extends AppCompatActivity {
    
        private ActivityMainBinding mMainBinding;
        private LayoutIncludeBinding mIncludeBinding;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            mMainBinding = ActivityMainBinding.inflate(getLayoutInflater());
            setContentView(mMainBinding.getRoot());
    
            mMainBinding.text.setText("dududududu");
    
            mMainBinding.include.includeText.setText("qqqqqqqqqqq");
    
        }
    }
    

    这就是套娃模式(当然名字是我起的)

     mMainBinding.include.includeText.setText("qqqqqqqqqqq");
    

    在布局嵌套多的时候,层层调用。
    这也很好理解, mMainBinding.include 这返回的是layout_include

     mMainBinding.include.includeText.setText("qqqqqqqqqqq");
    

    这行就是 layout_include 调用自己的includeText。

    别以为到这你就全会了,万一有一个布局用了 merge 怎么办???

    用到merge

    merge是一个解决父布局多余嵌套的一个标签,他不会最终加载到布局里,更多的是作为一个标志存在

    **比如我们修改 layout_include.xml **

    <?xml version="1.0" encoding="utf-8"?>
    <merge
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
    
        <TextView
            android:id="@+id/include_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="50sp" />
    
    </merge>
    

    这时候你再运行肯定就报错了,那是因为,merge并不会加载到布局里,而我们又给 include 添加了id,所以Viewbinding在生成 java类 的时候,随着id找过来,发现是merge,无从下手,就奔溃了。

    怎么解决这个问题呢??

    将include的id去掉不就行了, O

    你这会儿肯定又不乐意了,去掉怎么调用 include_text 呢???

    细心的小可爱肯定发现了上面的inflate的源码,第一个重载调用第二个重载,第二个返回 bind(root) 。

    bind 就是我们需要用到的方法了。

    public class MainActivity extends AppCompatActivity {
    
        private ActivityMainBinding mMainBinding;
        private LayoutIncludeBinding mIncludeBinding;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            mMainBinding = ActivityMainBinding.inflate(getLayoutInflater());
            setContentView(mMainBinding.getRoot());
            ...
    
            mIncludeBinding = LayoutIncludeBinding.bind(mMainBinding.getRoot());
            mIncludeBinding.includeText.setText("lalala");
        }
    }
    

    我们先声明了一个 LayoutIncludeBinding ,然后调用 LayoutIncludeBinding.bind(mMainBinding.getRoot()) 将其初始化,也就是将他绑定到 mMainBinding.getRoot() 上,也就是他的父布局。
    这时候我们再调用 mIncludeBinding.includeText.setText("lalala"); 就没问题了

    到此,关于ViewBinding基本都已经学完了,其他使用上的一些技巧就交给大家去探索了!

  • 相关阅读:
    Codeforces 611C. New Year and Domino 动态规划
    POJ2585 Window Pains 拓扑排序
    HDOJ1242 Rescue(营救) 搜索
    codeforces 数字区分 搜索
    ZOJ2412 Farm Irrigation(农田灌溉) 搜索
    hdu 4389 X mod f(x) 数位dp
    hdu 4734 F(x) 数位dp
    Codeforces Beta Round #51 D. Beautiful numbers 数位dp
    hdu 3652 B-number 数位dp
    bzoj 1026: [SCOI2009]windy数 数位dp
  • 原文地址:https://www.cnblogs.com/hairless/p/13428309.html
Copyright © 2020-2023  润新知