当前位置:   article > 正文

android databinding之include

android databinding include

由于前段时间了解到了google推出的数据绑定框架databinding,就使用它实现了一个简单的android的mvvm架构思想的demo。

使用过程之中很happy,按照其使用方式,框架会自动生成布局文件对应的XXXBinding类文件。再也不用findViewById了,也再也不用使用注解框架在Activity或者Fragment中写大量的控件属性了,哇,整个世界都清净了。。。。这感觉太爽了。。。

结果遇到问题了,也不知道怎么解决。。。。幸好有google老师带我们学习。

前面都是废话,下面就详细分析我遇到的问题吧!

使用一个Activity + 对应的布局文件举例:

DemoActivity:

  1. public class DemoActivity extends BaseActivity<DemoVM, ActivityDemoBinding> {
  2.     @Bind(R.id.linkTv)
  3.     TextView linkTv;
  4.     @Override
  5.     protected void onCreate(Bundle savedInstanceState) {
  6.         super.onCreate(savedInstanceState);
  7.         initWidget();
  8.     }
  9.     @Override
  10.     protected void initBinding() {
  11.         setBinding(DataBindingUtil.<ActivityDemoBinding>setContentView(this, R.layout.activity_demo));
  12.         binding.setVm(getViewModel());
  13.     }
  14.     @Override
  15.     protected void initModel() {
  16.     }
  17.     @Override
  18.     public void initViewModel() {
  19.         setViewModel(new DemoVM(this));
  20.     }
  21.     private void initWidget() {
  22.         linkTv.setText(Html.fromHtml(getResources().getString(R.string.url)));
  23.         linkTv.setMovementMethod(LinkMovementMethod.getInstance());
  24.     }
  25.     @Override
  26.     protected boolean hasBackButton() {
  27.         return false;
  28.     }
  29.     @Override
  30.     protected int getToolbarTitle() {
  31.         return R.string.title_activity_demo;
  32.     }

    activity_demo.xml(include了一个布局文件):

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <layout xmlns:android="http://schemas.android.com/apk/res/android"
  3.     xmlns:app="http://schemas.android.com/apk/res-auto"
  4.     xmlns:bind="http://schemas.android.com/apk/res-auto"
  5.     xmlns:tools="http://schemas.android.com/tools">
  6.     <data>
  7.         <import type="com.zdj.presentation.modules.demo.vms.DemoVM" />
  8.         <variable
  9.             name="vm"
  10.             type="DemoVM" />
  11.     </data>
  12.     <android.support.design.widget.CoordinatorLayout
  13.         android:layout_width="match_parent"
  14.         android:layout_height="match_parent"
  15.         android:fitsSystemWindows="true"
  16.         tools:context="com.zdj.presentation.modules.demo.views.DemoActivity">
  17.         <android.support.design.widget.AppBarLayout
  18.             android:layout_width="match_parent"
  19.             android:layout_height="wrap_content"
  20.             android:theme="@style/AppTheme.AppBarOverlay"
  21.             app:elevation="0dp">
  22.             <android.support.v7.widget.Toolbar
  23.                 android:id="@+id/toolbar"
  24.                 android:layout_width="match_parent"
  25.                 android:layout_height="?attr/actionBarSize"
  26.                 android:background="?attr/colorPrimary"
  27.                 app:popupTheme="@style/AppTheme.PopupOverlay" />
  28.         </android.support.design.widget.AppBarLayout>
  29.         <include
  30.             layout="@layout/content_demo"
  31.             bind:vm="@{vm}" />
  32.     </android.support.design.widget.CoordinatorLayout>
  33. </layout>

    content_demo.xml:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <layout xmlns:android="http://schemas.android.com/apk/res/android"
  3.     xmlns:app="http://schemas.android.com/apk/res-auto"
  4.     xmlns:bind="http://schemas.android.com/apk/res-auto"
  5.     xmlns:tools="http://schemas.android.com/tools">
  6.     <data parent="@">
  7.         <import type="com.zdj.presentation.modules.demo.vms.DemoVM"/>
  8.         <variable
  9.             name="vm"
  10.             type="DemoVM"/>
  11.     </data>
  12.     <LinearLayout
  13.         android:orientation="vertical"
  14.         android:layout_width="match_parent"
  15.         android:layout_height="match_parent"
  16.         android:paddingBottom="@dimen/activity_vertical_margin"
  17.         android:paddingLeft="@dimen/activity_horizontal_margin"
  18.         android:paddingRight="@dimen/activity_horizontal_margin"
  19.         android:paddingTop="@dimen/activity_vertical_margin"
  20.         app:layout_behavior="@string/appbar_scrolling_view_behavior"
  21.         tools:context="com.zdj.presentation.modules.demo.views.DemoActivity"
  22.         tools:showIn="@layout/activity_demo">
  23.         <TextView
  24.             android:id="@+id/linkTv"
  25.             android:layout_width="match_parent"
  26.             android:layout_height="wrap_content"
  27.             android:gravity="center"/>
  28.         <Button
  29.             android:id="@+id/btn_LoadData"
  30.             android:layout_width="match_parent"
  31.             android:layout_height="wrap_content"
  32.             android:text="@string/btn_text_load_data"
  33.             bind:onClickListener="@{vm.onClickLoadData}" />
  34.     </LinearLayout>
  35. </layout>

    由Activity的initWidget方法可见,若要使用content_demo中的TextView控件,还需要注解框架或者通过findViewById方法也行,找到指定的控件,然后对其处理。这样其实就是生成了两个控件实例在操作布局文件     中的控件了,可见的一个实例在Activity中,那么另一个呢?它在content_demo.xml生成的ContentDemoBinding类中,而activity_demo.xml生成的对应的数据绑定类ActivityDemoBinding含有ContentDemoBinding一个类型的私有的属性,而恰恰的想要操作的view是ContentDemoBinding的一个属性,activity是访问不到的。

    有没有什么办法完全使用databinding框架自动给我们生成的各个实例呢?这样好处至少有两个:1 不用使用findViewById 或者第三方注解框架  2 避免生成前面提到的两个控件实例对象

    下面介绍方法,其实很简单,针对activity_demo.xml做一点点的改变即可:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <layout xmlns:android="http://schemas.android.com/apk/res/android"
  3.     xmlns:app="http://schemas.android.com/apk/res-auto"
  4.     xmlns:bind="http://schemas.android.com/apk/res-auto"
  5.     xmlns:tools="http://schemas.android.com/tools">
  6.     <data>
  7.         <import type="com.zdj.presentation.modules.demo.vms.DemoVM" />
  8.         <variable
  9.             name="vm"
  10.             type="DemoVM" />
  11.     </data>
  12.     <android.support.design.widget.CoordinatorLayout
  13.         android:layout_width="match_parent"
  14.         android:layout_height="match_parent"
  15.         android:fitsSystemWindows="true"
  16.         tools:context="com.zdj.presentation.modules.demo.views.DemoActivity">
  17.         <android.support.design.widget.AppBarLayout
  18.             android:layout_width="match_parent"
  19.             android:layout_height="wrap_content"
  20.             android:theme="@style/AppTheme.AppBarOverlay"
  21.             app:elevation="0dp">
  22.             <android.support.v7.widget.Toolbar
  23.                 android:id="@+id/toolbar"
  24.                 android:layout_width="match_parent"
  25.                 android:layout_height="?attr/actionBarSize"
  26.                 android:background="?attr/colorPrimary"
  27.                 app:popupTheme="@style/AppTheme.PopupOverlay" />
  28.         </android.support.design.widget.AppBarLayout>
  29.         <!--    需要改变的地方:加上 android:id="@+id/views" 即可   -->
  30.         <include
  31.             layout="@layout/content_demo"
  32.             android:id="@+id/views"
  33.             bind:vm="@{vm}" />
  34.     </android.support.design.widget.CoordinatorLayout>
  35. </layout>

    布局文件修改之后,代码的变化,这里只贴了initWidget方法了,因为除了去除对BufferKnife的依赖以外(可以删除控件属性了),改变的只有这里:

  1. private void initWidget() {
  2.      // 终于可以在Activity中直接访问include的控件了,这个简单的问题困扰了我好长时间。。。。
  3.     binding.views.linkTv.setText(Html.fromHtml(getResources().getString(R.string.url)));
  4.     binding.views.linkTv.setMovementMethod(LinkMovementMethod.getInstance());
  5. }

    究其原因,其实是在ActivityDemoBinding类中添加了一个属性 public  final  ContentDemoBinding views,正好符合我的要求,提供了公共的访问权限。

    在布局文件中,所有带id的标签都会映射为布局文件生成的对象的一个属性,由生成的binding对象的构造函数可以看出来:

  1. public ActivityDemoBinding(android.databinding.DataBindingComponent bindingComponent, View root) {
  2.     super(bindingComponent, root, 2);
  3.     // 首先会将所有带id的view映射为object数组
  4.     final Object[] bindings = mapBindings(bindingComponent, root, 3, sIncludes, sViewsWithIds);
  5.     // 这里至于 view 对应的 bindings第几个元素,需要细究ViewDataBinding类的mapBindings方法
  6.     this.mboundView0 = (android.support.design.widget.CoordinatorLayout) bindings[0];
  7.     this.mboundView0.setTag(null);
  8.     this.toolbar = (android.support.v7.widget.Toolbar) bindings[2];
  9.     this.views = (com.zdj.presentation.databinding.ContentDemoBinding) bindings[1];
  10.     setRootTag(root);
  11.     // listeners
  12.     invalidateAll();
  13. }

    最后不忘贴出参考地址

转载于:https://my.oschina.net/zhangdengjiexuyu/blog/671244

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/320687
推荐阅读
相关标签
  

闽ICP备14008679号