安卓开发的时候有些很些经常重复又麻烦的东西总是希望越简单越好,下面给出DataBinding框架一些简单的使用方法,解决两个小问题。
- 总是findViewById 很烦?
- 更新UI时将数据映射到各个View很麻烦?(特别是子线程中更新UI)
简要介绍:
2015年谷歌I/O大会上介绍了一个框架DataBinding,DataBinding是一个数据绑定框架,以前我们在Activity里写很多的findViewById,现在如果我们使用DataBinding,就可以抛弃findViewById。DataBinding主要解决了两个问题:
- 需要多次使用findViewById,损害了应用性能且令人厌烦
- 更新UI数据需切换至UI线程,将数据分解映射到各个view比较麻烦
(官网文档说还会提高解析XML的速度)
使用方法:
第一步:在module 的 build.gradle的android{}里面加入
dataBinding{
enabled true
}
第二步:在需要用到的Activity对应的XML文件下
<?xml version="1.0" encoding="utf-8"?>
<layout>
<data class= "ActivityMain">
</data>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.zjz.mvvmtest.MainActivity">
</RelativeLayout>
</layout>
第三步:
Activity文件加载布局
package com.zjz.mvvmtest;
import android.databinding.DataBindingUtil;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import com.zjz.mvvmtest.databinding.ActivityMain;
public class MainActivity extends AppCompatActivity {
private ActivityMain binding;//这个类是自动生成的,用的时候导一下包就好了
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//通过DataBInding加载布局都会对应的生成Binding对象,对象的类名就是在XML中设置好的
binding = DataBindingUtil.setContentView(MainActivity.this,R.layout.activity_main);
}
}
自定义类的命名(有些奇怪)
网上很多都说默认的类命名是 xml文件名加Binding作为后缀,例如ActivityMainBinding ,但是根本找不到这个类,所以我们要自定义类名。
<?xml version="1.0" encoding="utf-8"?>
<layout>
<data class= "MainActivityBinding">
</data>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.zjz.mvvmtest.MainActivity">
</RelativeLayout>
</layout>
我自定义了MainactivityBinding (Activity类名加上Binding做后缀),但是我试过改成默认的那种,还是找不到,我也不知道为什么,很奇怪。
用处1:绑定基本数据和String
<?xml version="1.0" encoding="utf-8"?>
<layout>
<data class = "Main2ActivityBinding">
<!--绑定基本数据类型及String-->
<!--name: 和java代码中的对象是类似的,名字自定义-->
<!--type: 和java代码中的类型是一致的-->
<variable
name="content"
type="String" />
<variable
name="abc"
type="String" />
<variable
name="enabled"
type="boolean" />
</data>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:orientation="vertical"
tools:context="com.zjz.mvvmtest.Main2Activity">
<!--绑定基本数据类型及String的使用是通过 @{数据类型的对象} 通过对应数据类型的控制显示-->
<Button
android:id="@+id/btn_main2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="@{enabled}"
android:text="@{content}" />
<Button
android:id="@+id/btn2_main2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>
</layout>
然后在代码中binding会产生相应的方法。去设置这些属性。
binding = DataBindingUtil.setContentView(Main2Activity.this, R.layout.activity_main2);
binding.setContent("我绑定了哦");
binding.setEnabled(false);
// binding.btn2Main2.setClickable(false);没用的
// binding.btn2Main2.setEnabled(false);有用
binding.btnMain2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
binding.btnMain2.setText("更改成功");
}
});
binding.btn2Main2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
binding.btn2Main2.setText("更改成功");
}
});
}
用处2:绑定model数据
控件和model绑定在一起,可以通过改变model去更新UI
首先看看XML文件
<?xml version="1.0" encoding="utf-8"?>
<layout>
<data class = "Main3ActivityBinding">
<variable
name="user" <!-名称->
type="com.zjz.mvvmtest.User"/> <!-model的位置(引用)->
</data>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main3"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.zjz.mvvmtest.Main3Activity">
<Button
android:id="@+id/btn_main3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{user.text}"/>
<Button
android:id="@+id/btn2_main3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{user.text}"/>
</LinearLayout>
</layout>
在Activity中:
binding = DataBindingUtil.setContentView(Main3Activity.this, R.layout.activity_main3);
final User user = new User("这里可以绑定设置内容");
binding.setUser(user);
binding.btnMain3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
user.setText("数据更新成功");
binding.setUser(user);//更新UI
}
});
在子线程中更新数据(错误方法):
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main4);
textView = (TextView) findViewById(R.id.tv);
Button button = (Button) findViewById(R.id.btn_main4);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new Thread(new Runnable() {
@Override
public void run() {
textView.setText("更新成功");//直接在子线程中更新UI,不可取
}
}).start();
}
});
}
上面方法明显会崩。子线程中不能更新UI。
下面是采用DataBinding框架的
binding.btn2Main3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new Thread(new Runnable() {
@Override
public void run() {
// binding.btn2Main3.setText("另一种方式在线程中更新");会崩
user.setText("再线程中数据更新成功");
binding.setUser(user);//更新UI
}
}).start();
}
});
这样就能成功了!(很方便)