初步了解DataBinding(数据绑定)
程序员文章站
2022-06-08 16:30:55
...
初步了解DataBinding(数据绑定)
关于JetPack中的DataBinding(数据绑定)
数据绑定库是一种支持库,借助该库,您可以使用声明性格式(而非程序化地)将布局中的界面组件绑定到应用中的数据源。
简言之一句话:通过DataBingding隔离开controller与View的紧密联系
创建实例
首先使用常用方法实现点击按钮文本记录自增1
本文为学习类文档,通过学习B站up主longway777的视频,如有侵权,请联系博主进行删除
布局文件
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/helloworld"
android:textSize="36sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.498"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.247" />
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/button"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
创建ViewModel类
ViewModel类继承ViewModel
package com.example.databindingdemo;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
public class MyViewModel extends ViewModel {
private MutableLiveData<Integer> number;
public MutableLiveData<Integer> getNumber() {
if (number == null){
number = new MutableLiveData<>();
number.setValue(0);
}
return number;
}
public void add(){
number.setValue(number.getValue()+1); //通过setValue实现数据更新
}
}
在MainActivity.java中声明变量
package com.example.databindingdemo;
import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModel;
import androidx.lifecycle.ViewModelProvider;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
Button button;
TextView textView;
MyViewModel myViewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = findViewById(R.id.button);
textView = findViewById(R.id.textView);
myViewModel = new ViewModelProvider(this).get(MyViewModel.class);
myViewModel.getNumber().observe(this, new Observer<Integer>() {
@Override
public void onChanged(Integer integer) {
textView.setText(String.valueOf(integer));
}
}); //对LiveData的一个观察
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
myViewModel.add();
}
});
}
}
实现效果如下:
使用DataBinding来改写改善代码部分
上述部分每次变量都要声明进行链接,大量内容时会麻烦
程序编译时存在隐患,在项目创建阶段更改时会造成增删的改动,使程序难以维护,因此使用DataBinding来改写
- 首先将应用配置为使用数据绑定,请在应用模块的 build.gradle 文件中添加 dataBinding 元素,如以下示例所示:
android {
...
dataBinding {
enabled = true
}
}
注意:即使应用模块不直接使用数据绑定,也必须为依赖于使用数据绑定的库的应用模块配置数据绑定。
- 切换至界面布局文件中将布局转换成data binding Layout:
数据绑定布局文件略有不同,以根标记 layout 开头,后跟 data 元素和 view 根元素。转换后的布局如下:
<?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>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/textView_show"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/helloworld"
android:textSize="36sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.498"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.247" />
<Button
android:id="@+id/button_click"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/button"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
- 在controller中将MainActivity.java文件进行修改,读者可上下对比进行研究
package com.example.databindingdemo;
import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import com.example.databindingdemo.databinding.ActivityMainBinding;
public class MainActivity extends AppCompatActivity {
//Button button;
//TextView textView;
MyViewModel myViewModel;
ActivityMainBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_main);
binding = DataBindingUtil.setContentView(this,R.layout.activity_main); //xml中的标签即类似成为了binding的内部类
//textView = findViewById(R.id.textView_show);
//button = findViewById(R.id.button_click);
myViewModel = new ViewModelProvider(this).get(MyViewModel.class);
myViewModel.getNumber().observe(this, new Observer<Integer>() {
@Override
public void onChanged(Integer integer) {
//textView.setText(String.valueOf(integer));
binding.textViewShow.setText(String.valueOf(integer));
}
}); //对LiveData的一个观察
// button.setOnClickListener(new View.OnClickListener() {
// @Override
// public void onClick(View v) {
// myViewModel.add();
// }
// });
binding.buttonClick.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
myViewModel.add();
}
});
}
}
界面运行时没问题的
4. 也可逆向绑定将点击事件绑定至Layout中
使用上述Layout中的
<data>
</data>
这组标签即可实现功能。
<?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="data"
type="com.example.databindingdemo.MyViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/textView_show"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{String.valueOf(data.number)}"
android:textSize="36sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.498"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.247" />
<Button
android:id="@+id/button_click"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/button"
android:onClick="@{()->data.add()}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
- 对controller进行再精简
package com.example.databindingdemo;
import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import com.example.databindingdemo.databinding.ActivityMainBinding;
public class MainActivity extends AppCompatActivity {
//Button button;
//TextView textView;
MyViewModel myViewModel;
ActivityMainBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_main);
binding = DataBindingUtil.setContentView(this,R.layout.activity_main); //xml中的标签即类似成为了binding的内部类
//textView = findViewById(R.id.textView_show);
//button = findViewById(R.id.button_click);
myViewModel = new ViewModelProvider(this).get(MyViewModel.class);
binding.setData(myViewModel); //在Layout中设置了一个variable,需要在此设value
binding.setLifecycleOwner(this);
// myViewModel.getNumber().observe(this, new Observer<Integer>() {
// @Override
// public void onChanged(Integer integer) {
// //textView.setText(String.valueOf(integer));
// binding.textViewShow.setText(String.valueOf(integer));
// }
// }); //对LiveData的一个观察
// button.setOnClickListener(new View.OnClickListener() {
// @Override
// public void onClick(View v) {
// myViewModel.add();
// }
// });
// binding.buttonClick.setOnClickListener(new View.OnClickListener() {
// @Override
// public void onClick(View v) {
// myViewModel.add();
// }
// });
}
}
删除注释行可看到精简之后的最终controller代码极少
package com.example.databindingdemo;
import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil;
import androidx.lifecycle.ViewModelProvider;
import android.os.Bundle;
import com.example.databindingdemo.databinding.ActivityMainBinding;
public class MainActivity extends AppCompatActivity {
MyViewModel myViewModel;
ActivityMainBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = DataBindingUtil.setContentView(this,R.layout.activity_main); //xml中的标签即类似成为了binding的内部类
myViewModel = new ViewModelProvider(this).get(MyViewModel.class);
binding.setData(myViewModel); //在Layout中设置了一个variable,需要在此设value
binding.setLifecycleOwner(this);
}
}
功能依旧正常,且翻转数据不会丢失