【Jetpack】DataBinding(三):布局绑定类

QuibblerQuibbler 2020-12-27 约 14 分钟 1816 次阅读

DataBinding(三):布局绑定类

写好我们的DataBinding布局之后如何使用呢?如何初始化在<data />中定义的变量呢?

1、绑定布局

已经将原来的XML布局转换成DataBinding支持的数据绑定布局,接下来就是将它设置给我们的Activity、Fragment等需要加载布局的地方。

1.1、Activity中绑定布局

在使用DataBinding之前通过setContentView(int layoutResID)方法设置Activity布局:

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_data_binding);
    }

启用DataBinding后,有两种方式加载data binding layout布局:

①使用DataBinding库中的DataBindingUtil.setContentView()方法给当前Activity设置布局,返回自动生成的绑定类实例:

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        DataBindingLayoutBinding dataBindingBinding = DataBindingUtil.setContentView(this, R.layout.data_binding_layout);
    }

②或者先通过生成绑定类的inflate()静态方法加载布局,再通过Activity的setContentView(View view)方法设置当前Activity的布局。看似这种方法没有显示的指定layout,实际上MainLayoutBinding对应的xml不就是我们要加载的布局吗?

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        MainLayoutBinding dataBindingBinding = MainLayoutBinding.inflate(getLayoutInflater());
        setContentView(dataBindingBinding.getRoot());
    }

1.2、Fragment中绑定布局

在自定义Fragment的onCreateView()中一般通过DataBindingUtil的inflate()方法绑定布局:

@Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        FragmentBlankBinding fragmentBlankBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_blank, container, false);
        ... ...
        return fragmentBlankBinding.getRoot();
    }

1.3、RecyclerView绑定布局

在RecyclerView等组件中通过DataBindingUtil.inflate()方法加载布局:

@Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        RecyclerViewItemBinding recyclerViewItemBinding = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()),
                R.layout.recycler_view_item, parent, false);
        //设置DataBinding值
        ... ...
        return new ViewHolder(recyclerViewItemBinding);
    }

1.4、未知类型的绑定

实际项目中List、RecyclerView很复杂,加载的布局在加载前可能是未知的,无法预知加载哪个布局,或者可以加载多种类型的布局。这时候可以先加载xml布局,在将其设置给ViewDataBinding通用的抽象类型变量:

@Override
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        //LayoutInflater从xml数据绑定布局加载View
        View view = inflater.inflate(R.layout.fragment_blank, container, false);
        //将View设置给ViewDataBinding
        ViewDataBinding fragmentBlankBinding = DataBindingUtil.bind(view);
        //...
        return view;
    }

2、绑定类 extends ViewDataBinding

DataBinding根据data binding layout布局为我们自动生成对应的Binding类,在项目的build/generated/data_binding_base_class_source_out/debug/out/包名/databinding目录下。继承自ViewDataBinding抽象类,实现ViewBinding接口:

/** A type which binds the views in a layout XML to fields. */
    public interface ViewBinding {
        /**
         * Returns the outermost {@link View} in the associated layout file. If this binding is for a
         * {@code <merge>} layout, this will return the first view inside of the merge tag.
         */
        @NonNull
        View getRoot();
    }

2.1、ViewDataBinding抽象类

ViewDataBinding抽象类是所有自动生成的绑定类的父类,实现了ViewBinding接口,并且提供一些通用的方法。

public abstract class ViewDataBinding extends BaseObservable implements ViewBinding {
        /**
         * The root View that this Binding is associated with.
         */
        private final View mRoot;
        
        @Override
        public View getRoot() {
            return mRoot;
        }
        public abstract boolean setVariable(int variableId, @Nullable Object value);
        ...
    }

2.2、绑定类名称规则

类名称基于布局文件的名称:首字母大写的驼峰命名法并在末尾添加Binding后缀。比如布局文件名为 data_binding_layout.xml,因此生成的对应类为 DataBindingLayoutBinding,包含从布局属性到布局视图的所有绑定变量,并且知道如何为绑定表达式指定值。

还可以在<data />中用class指定生成的绑定类名:

<data class="MainLayoutBinding">
        ...
    </data>

2.3、获取控件

布局中原来是通过findViewById获取其中的控件。现在在DataBinding布局中定义控件,要获取的控件必须要有id,否则无法获取到:

<TextView
        android:id="@+id/text_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@{name}" />

直接通过DataBinding布局对象就可以拿到其中的控件对象,无需再通过findViewById。对象名是id去除下划线的驼峰命名法:

TextView textView = dataBindingBinding.textView;

getRoot()方法是通用的方法,可以获取根布局View对象。

2.4、变量setter/getter

在布局中定义了属性如何初始化设置值呢?数据绑定库为布局中声明的每个变量生成访问器方法。比如在布局中定义了String类型的变量name:

<variable
        name="name"
        type="String" />

在自动生成的DataBinding对象中就会有对应的setter和getter方法:

//设置
    dataBindingBinding.setName("");
    //获取
    dataBindingBinding.getName();

2.5、BR类

数据绑定库在模块包中生成一个名为BR的类,在项目的build/generated/ap_generated_sources/debug/out/androidx/databinding/library/baseAdapters/BR.java目录下,其中包含用于数据绑定的资源的 ID。

通过该BR中的ID,调用父类ViewDataBinding的setVariable(int variableId,Object value)方法同样可以设置指定ID资源的值:

dataBindingBinding.setVariable(BR.name, "Quibbler");

这种方法特别有用,尤其是对于变量无法预先知道的data binding layout。

3、其它

使用ViewDataBinding有一些注意点,以后遇到其它问题会继续补充,记录经验。

3.1、线程安全

以前我们知道在开发Android的时候,子线程中设置View数据是不安全的。但是ViewDataBinding以在后台线程中更改数据模型(这个模型不能是集合)。数据绑定会在求值过程中对每个变量/字段进行本地化,以避免出现并发问题。

参考资料:

         Libraries > Databinding">Jetpack > Libraries > Databinding

        Data Binding:Generated binding classes

        

相关推荐

精选
ViewPager和PagerAdapter、FragmentPagerAdapter、FragmentStatePager
Android

ViewPager和PagerAdapter、FragmentPagerAdapter、FragmentStatePager

ViewPager1、ViewPagerandroidx.viewpager.widget.ViewPager,Android中使用非常广泛的控件,可以说是APP必备:首次打开引导页、页面Banner广告等。常用方法:setAdapter() 设置适配器setOffscreenPageLimit() 设置缓存的页面个数,默认是 1setCurrentItem() 跳转到特定的页面setOnPage

1.1k
获取Android内置WebView内核版本
Android

获取Android内置WebView内核版本

获取Android内置WebView内核版本竟然能遇到这样奇葩的事情,网页用的技术过于新颖,以至于只支持高版本Chromium内核的,低版本安卓系统中内置的内核版本较低,无法加载前端页面。1、设置查看在系统设置里 > 应用 > 应用管理 > 显示系统应用,查看WebView组件:2、页面查看通过WebView发起的网络请求,都会带上浏览器的UA,通常页面都可以通过UA判断浏览器的内核版本。这里有两

1.1w
Android 14适配总结
Android

Android 14适配总结

Android 14适配总结毕业工作至今已经适配了三个Android大版本,从Android 11到Android 12、再到Android 13。2023年,Google即将推出的Android 14,上半年已经开始第一批适配。现在,第四个Android版本已经适配完,总结记录一下。1、Android 14计划Google一般会在2月份对外发布预告,同时放出开发者预览版。“拉通”各大平台、厂商以

1.1w