欢迎光临
我们一直在努力

【实战】Android Data Binding从抵触到爱不释手

1 引入

如何高效地实现以下界面?

 

登录/未登录

有好几年findViewById实战经验的我,感觉并不难啊。一般会

1.先定义一个User的Model类,数据来自JSON解析;

2.创建一个xml,随后在xml中布局完所有View,对头像、标题、积分、登录按钮一个id;

3.在Activity中通过findViewById获取到头像ImageView、标题TextView、积分TextView、登录Button,然后给Button设置监听器,再根据登陆状态展示对应数据;

实现如下:

  • User.java 

 

  • activity_detail.xml

 

  • DetailActivity

 

2 去掉烦人的findViewById(View注入)

可以看到,在Activity中View的定义、find、判空占据了大量篇幅,我们需要更优雅的实现。

2.1 ButterKnife

你可能听说过Jake Wharton的ButterKnife,这个库只需要在定义View变量的时候通过注解传入对应id,随后在onCreate时调用ButterKnife.bind(this)即可完成view的注入,示例如下:

 

2.2 Android Data Binding

如果使用了Android Data Binding,那么View的定义、find、判空这些都不用写了,如何做呢?

2.2.1 准备工作

首先,你需要满足一个条件:你的Android Plugin for Gradle版本必须等于或高于1.5.0-alpha1版本,这个版本位于根目录build.gradle中,示例如下:


 
  1. buildscript { 
  2.     repositories { 
  3.         jcenter() 
  4.     } 
  5.     dependencies { 
  6.         classpath 'com.android.tools.build:gradle:2.1.0-rc1' 
  7.     } 
  8.  

接着,你必须告诉编译器开启Data Binding,一般位于app:build.gradle的android标签中,示例如下:


 
  1. android { 
  2.     compileSdkVersion 23 
  3.     buildToolsVersion "23.0.2" 
  4.  
  5.     dataBinding { 
  6.         enabled true 
  7.     } 
  8.     ... 
  9.  

2.2.2 修改layout.xml

以activity_detail.xml为例,原来的根节点为LinearLayout,如下所示:

 

2.2.3 开始享受乐趣吧!

在上述操作完成后,编译器会自动为我们生成

com.asha.demo.databinding.ActivityDetail2Binding.java类,这个类的命令方式为:包名 + databinding + activity_detail2驼峰命名方式 + Binding.java。随后,使用这个activity_detail2的DetailActivity2.java的代码可以简化为:


 
  1. public class DetailActivity2 extends AppCompatActivity { 
  2.  
  3.     ActivityDetail2Binding binding;    @Override 
  4.     protected void onCreate(@Nullable Bundle savedInstanceState) {        super.onCreate(savedInstanceState); 
  5.         binding = DataBindingUtil.setContentView(this,R.layout.activity_detail2); 
  6.  
  7.         login(); 
  8.     }    private void login(){ fill(User.newInstance()); }    private void logout(){ fill(null); }    private void fill(final User user){        final int visibility = user != null ? View.VISIBLE : View.GONE;        if (user != null){ 
  9.             binding.detailAvatar.setImageDrawable(ContextCompat.getDrawable(this,user.getAvatar())); 
  10.             binding.detailName.setText(user.getName()); 
  11.             binding.detailDesc.setText(String.format("积分:%d 等级:%d",user.getScore(),user.getLevel())); 
  12.         } 
  13.  
  14.         binding.detailAvatar.setVisibility(visibility); 
  15.         binding.detailName.setVisibility(visibility); 
  16.         binding.detailDesc.setVisibility(visibility); 
  17.         binding.detailActionButton.setOnClickListener(new View.OnClickListener() {                @Override 
  18.                 public void onClick(View v) {                if (user == null) login();                else logout(); 
  19.             } 
  20.         }); 
  21.         binding.detailActionButton.setText(user == null ? "登录":"退出登录"); 
  22.     } 

是的,所有View的定义、find、判空都不见了,所有的这些操作都在编译器为我们生成的ActivityDetail2Binding.java中完成,只需要在onCreate时调用如下代码进行setContentView即可实现,

binding = DataBindingUtil.setContentView(this,R.layout.activity_detail2);

我的天哪

2.2.4 ActivityDetail2Binding中注入View相关的代码分析

可以在as中方便的查看编译器自动生成的类,这个类位于/app/build/intermediates/classes/debug/com/asha/demo/databinding/ActivityDetail2Binding.class中,缩减掉Binding逻辑后的代码为:

 

其中全局静态SparseIntArray数组中存放了4个数字,这个四个数字为R.java中生成的对应View的id,


 
  1. public final class R { 
  2.     ...    public static final class id { 
  3.         ...        public static final int detail_action_button = 2131492951;        public static final int detail_avatar = 2131492948;        public static final int detail_desc = 2131492950;        public static final int detail_name = 2131492949; 
  4.         ... 
  5.     } 
  6.     ... 

 在ActvityDetail2Binding实例构造的时候调用了mapBindings,一次解决了所有View的查找,mapBindings函数在ActvityDetail2Binding父类ViewDataBinding中实现。

3 使用表达式在layout.xml中填充model数据

在ActivityDetail2.java中还存在大量的View控制、数据填充代码,如何把这些代码在交给layout.xml完成呢?

3.1 ModelAdapter类

第2节中已经定义了User.java类作为Model类,但是我们经常会遇到Model类和真正View展示不一致的情况,本例子中定义一个来ModelAdapter类来完整Model数据到展示数据的适配。示例代码为ActivityDetail3.java的内部类,可以调用ActivityDetail3.java中的函数,代码定义如下:

 

3.2 activity_detail3.xml中使用model

同样复制一份activity_detail2.xml为activity_detail3.xml,在<layout>节点加入<data>节点,并且在里面定义需要用的model类(比如ModelAdapter adapter),当然也可以是基础类型变量(比如int visibility);

随后,就可以在下面的view中使用表达式了,全部布局文件如下:

  1. <?xml version="1.0" encoding="utf-8"?><layout xmlns:android="http://schemas.android.com/apk/res/android"
  2.     <data> 
  3.         <variable name="adapter" type="com.asha.demo.DetailActivity3.ModelAdapter"/> 
  4.         <variable name="visibility" type="int"/> 
  5.     </data> 
  6.     <LinearLayout 
  7.         android:orientation="vertical" android:layout_width="match_parent" 
  8.         android:layout_height="match_parent"
  9.         <View 
  10.             android:background="@color/detail_background" 
  11.             android:layout_width="match_parent" 
  12.             android:layout_height="66dp"
  13.         </View
  14.         <ImageView 
  15.             android:src="@{adapter.avatar}" 
  16.             android:visibility="@{visibility}" 
  17.             android:id="@+id/detail_avatar" 
  18.             android:layout_gravity="center" 
  19.             android:layout_marginTop="-33dp" 
  20.             android:layout_width="66dp" 
  21.             android:layout_height="66dp" /> 
  22.         <TextView 
  23.             android:visibility="@{visibility}" 
  24.             android:text="@{adapter.name}" 
  25.             android:id="@+id/detail_name" 
  26.             android:textSize="17sp" 
  27.             android:textColor="@color/textColorPrimary" 
  28.             android:layout_marginTop="15dp" 
  29.             android:layout_gravity="center" 
  30.             android:layout_width="wrap_content" 
  31.             android:layout_height="wrap_content" /> 
  32.         <TextView 
  33.             android:visibility="@{visibility}" 
  34.             android:text="@{adapter.desc}" 
  35.             android:id="@+id/detail_desc" 
  36.             android:layout_marginTop="15dp" 
  37.             android:textSize="13sp" 
  38.             android:layout_gravity="center"%3

赞(0) 打赏
未经允许不得转载:九八云安全 » 【实战】Android Data Binding从抵触到爱不释手

评论 抢沙发