Android DataBinding 你好!
一:使用DataBinding的第一步,只需要在app/build.gradle
开启它
android {
compileSdkVersion 28
defaultConfig {
applicationId "azhon.com.viewbinding"
//....
}
//开启dataBinding
dataBinding {
enabled = true
}
}
二:将布局文件根元素修改为<layout>
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<import />
<variable />
</data>
<!-- layout 下只能有一个子节点 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- 布局内容 -->
</LinearLayout>
</layout>
- 在布局文件中我们可以通过快捷修复来将布局文件自动修改为符合databinding的布局
- 需要注意的是:layout 下只能有一个子节点
三:下面通过一些实例来介绍具体的使用
①为TextView绑定一个UserName
- 首先需要在
xml
中指定variable
数据,然后在TextView进行绑定,如下:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<!-- 指定数据 -->
<variable
name="userName"
type="String" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="40dp"
android:gravity="center"
android:text="@{userName,default=我是默认的值}"
android:textColor="#333333" />
</LinearLayout>
</layout>
- 在Activity中对这个布局加载,然后在设置
userName
的值
public class FirstMainActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
FirstMainBinding dataBinding = DataBindingUtil.setContentView(this, R.layout.first_main);
//设置数据
dataBinding.setUserName("Hello 阿钟");
}
}
1、Activity加载布局需要使用DataBindingUtil.setContentView()
,然后返回当前布局的*Binding对象,此类的命名规则为布局文件名称的驼峰命名
加上Binding:如activity_main
则为ActivityMainBinding
2、在布局中都是通过@{}
来进行引用变量、数据等
3、如果需要对字符串进行拼接的话就需要这样子写'@{"拼接字符串"+userName}'
②当然在布局中也是可以直接使用List、Map等
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<!--引入数据类型-->
<import type="java.util.List" />
<import type="java.util.Map" />
<!--与元素类型 "variable" 相关联的 "type" 属性值不能包含 '<' 字符。
这里 < 需要被转义为 <-->
<variable
name="list"
type="List<String>" />
<variable
name="map"
type="Map<String,String>" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<!--取list集合中的第一个元素-->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{list[0]}"/>
<!--取map集合中key = "key"元素-->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text='@{map.get("key")}' />
</LinearLayout>
</layout>
然后通过当前布局文件的Binding对List
、Map
进行赋值,如下:
public class FirstMainActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
FirstMainBinding dataBinding = DataBindingUtil.setContentView(this, R.layout.first_main);
//设置数据
dataBinding.setList(Arrays.asList("Larry", "Moe", "Curly"));
HashMap<String, String> map = new HashMap<>();
map.put("key", "我是map的值");
dataBinding.setMap(map);
}
}
③对View进行onClick
事件绑定
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="model"
type="com.azhon.viewbinding.FirstMainActivity" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<!--第一种写法-->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{model::click}"/>
<!--第二种写法-->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{model.click}"/>
<!--第三种写法-->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{()-> model.click2()}"/>
<!--第四种写法 调用有参数的函数-->
<!--theView 指代当前的TextView-->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{(thisView)-> model.click3(thisView,12)}"/>
</LinearLayout>
</layout>
相对应的Activity代码
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
FirstMainBinding dataBinding = DataBindingUtil.setContentView(this, R.layout.first_main);
//对model进行赋值
mainBinding.setModel(this);
}
public void click(View view) {
Toast.makeText(this, "DataBinding点击事件", Toast.LENGTH_SHORT).show();
}
public void click2() {
Toast.makeText(this, "DataBinding点击事件(无参数)", Toast.LENGTH_SHORT).show();
}
public void click3(View view, int p) {
Toast.makeText(this, "DataBinding点击事件,参数:" + p, Toast.LENGTH_SHORT).show();
}
}
④在布局中进行少量的运算,所支持的运算符如下:
!=
、%
、+
、-
、*
、/
、<
、>
、==
、<=
、>=
、<<
、>>
、>>>
或者使用三目运算符show ? View.VISIBLE : View.GONE
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<!--导入View类-->
<import type="android.view.View" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{String.valueOf(index + 1)}"
android:visibility="@{age > 13 ? View.GONE : View.VISIBLE}"
android:transitionName='@{"image_" + id}'/>
</LinearLayout>
</layout>
四:dataBinding结合RecyclerView进行使用
①布局文件中添加RecyclerView
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
</layout>
②创建一个实体类,用来做为RecyclerView的数据源User
public class User {
private String userName;
private String userNum;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserNum() {
return userNum;
}
public void setUserNum(String userNum) {
this.userNum = userNum;
}
}
③编写RecyclerView
的Item布局,引入User
这个实体类
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<!-- Item的数据源为User -->
<variable
name="user"
type="com.azhon.viewbinding.User" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#eeeeee"
android:gravity="center_vertical"
android:orientation="vertical"
android:paddingHorizontal="16dp"
android:paddingVertical="8dp">
<TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text='@{"姓名:"+user.userName,default=阿钟}' />
<TextView
android:id="@+id/tv_num"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text='@{"序号:"+user.userNum,default=123456}' />
</LinearLayout>
</layout>
④结合DataBinding
创建RecycleerView适配器
public class TestAdapter extends RecyclerView.Adapter<TestAdapter.MyViewHolder> {
private List<User> users;
private Context context;
public TestAdapter(List<User> users, Context context) {
this.users = users;
this.context = context;
}
@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int i) {
LayoutInflater inflater = LayoutInflater.from(context);
ItemRvBinding binding = DataBindingUtil.inflate(inflater, R.layout.item_rv, parent, false);
return new MyViewHolder(binding.getRoot());
}
@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int i) {
ItemRvBinding binding = DataBindingUtil.getBinding(holder.itemView);
binding.setUser(users.get(i));
//迫使数据立即绑定
binding.executePendingBindings();
}
@Override
public int getItemCount() {
return users.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder {
public MyViewHolder(View itemView) {
super(itemView);
}
}
}
- 通过
DataBindingUtil.inflate()
加载Item的布局,返回Item的*Binding对象 - 在
onBindViewHolder
中设置Item的数据binding.setUser(users.get(i));
需要调用binding.executePendingBindings();
对数据进行立即绑定,防止数据错乱
⑤接下来就简单了,为Adapter设置数据即可
FirstMainBinding dataBinding = DataBindingUtil.setContentView(this, R.layout.first_main);
//通过dataBinding找到布局View
RecyclerView recyclerView = dataBinding.rv;
recyclerView.setLayoutManager(new LinearLayoutManager(this));
List<User> users = new ArrayList<>();
for (int i = 0; i < 30; i++) {
User user = new User();
user.setUserName("用户 " + i);
user.setUserNum(String.valueOf(Math.round(Math.random()) * 100000));
users.add(user);
}
TestAdapter adapter = new TestAdapter(users, this);
recyclerView.setAdapter(adapter);