defaultConfig { applicationId "com.example.databinding_viewmodel_livedata" minSdkVersion 15 targetSdkVersion 30 versionCode 1 versionName "1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" //开启对databinding的支持 dataBinding{ enabled = true } }
<?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="viewModel" type="com.example.databinding_viewmodel_livedata.MyViewModel" /> </data> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> </androidx.constraintlayout.widget.ConstraintLayout> </layout>
//绑定类名 = 布局名称(转换为驼峰) + Binding ActivityMainBinding activityMainBinding = DataBindingUtil.setContentView(this,R.layout.activity_main);
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { final FragmentFirstBinding fragmentFirstBinding = DataBindingUtil.inflate(inflater,R.layout.fragment_first,container,false); return fragmentFirstBinding.getRoot(); }
1.声明标签
<data> <variable name="viewModel" type="com.example.databinding_viewmodel_livedata.MyViewModel" /> </data>
表示在layout布局文件中,声明一个变量
变量的类型: com.example.databinding_viewmodel_livedata.MyViewModel
变量的名称: viewModel
变量由 DataBinding对象 赋值 :
ActivityMainBinding activityMainBinding = DataBindingUtil.setContentView(this,R.layout.activity_main); MyViewModel myViewModel = new ViewModelProvider(this).get(MyViewModel.class); activityMainBinding.setViewModel(myViewModel);
2.导入标签
<data> <import type="com.example.databinding_viewmodel_livedata.AppUtils" alias="appUtils"/> </data>
表示在layout布局文件中,导入一个类
alias=“appUtils” : 给类起别名 (可不设置)
类中存在静态方法: madeNewScore(int score) ,可直接调用:
<TextView android:id="@+id/tvScore" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{appUtils.madeNewScore(viewModel.score)}" android:textSize="30sp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" />
1.创建文件名称为 include_layout 的 include布局
<?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android"> <data> <variable name="includeViewModel" type="com.example.databinding_viewmodel_livedata.MyViewModel" /> </data> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@{String.valueOf(includeViewModel.num)}" android:textSize="22sp" /> </LinearLayout> </layout>
2.使用include布局
<include app:includeViewModel="@{viewModel}" layout="@layout/include_layout" />
includeViewModel : 在include布局文件定义的 变量名称
app:includeViewModel="@{viewModel}": 将该布局数的viewModel变量 赋值给 include布局中的includeViewModel变量
相似于给view添加onClick()方法
public class MyHandlers { public void onClickFriend(View view) { ... } }
<?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android"> <data> <variable name="handlers" type="com.example.MyHandlers"/> <variable name="user" type="com.example.User"/> </data> <LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{user.firstName}" android:onClick="@{handlers::onClickFriend}"/> </LinearLayout> </layout>
public class Presenter { public void onSaveClick(Task task){} }
<?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android"> <data> <variable name="task" type="com.android.example.Task" /> <variable name="presenter" type="com.android.example.Presenter" /> </data> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="@{() -> presenter.onSaveClick(task)}" /> </LinearLayout> </layout>
此处示例实现了 LiveData + ViewModel + DataBinding 的结合
意义: 实现了单向绑定, 当ViewModel中的值(LiveData包裹)发生变化时,界面会自动发生变化
public class BindingAdapterManager { @BindingAdapter(value = {"imageUrl","imageLocal"},requireAll = false) public static void setImage(ImageView imageView,String imageUrl,int resId){ if (!TextUtils.isEmpty(imageUrl)){ Glide.with(imageView.getContext()).load(imageUrl).into(imageView); }else { Glide.with(imageView.getContext()).load(resId).into(imageView); } } }
上图相当于给Binding布局中的 ImageView标签 添加 imageUrl属性 和 imageLocal属性
其中 ImageView标签源于方法的第一个参数
imageUrl属性 和 imageLocal属性 源于 BindingAdapter注解中的两个value值
BindingAdapter注解中value值 接收的是一个数组,意味着可以给 ImageView标签 添加任意个数的属性
requireAll : true: 默认, 如果声明的value没有被全部设置,则无法编译 false: 允许只有部分值被设置
通过绑定适配器,可以将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> <variable name="viewModel" type="com.example.databinding_viewmodel_livedata.MyViewModel" /> </data> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_horizontal" android:orientation="vertical" android:padding="40dp" tools:context=".MainActivity"> <ImageView app:imageUrl="@{viewModel.imgUrl}" app:imageLocal="@{viewModel.imgLocalResId}" android:layout_width="match_parent" android:layout_height="200dp"/> </LinearLayout> </layout>
public class MyViewModel extends ViewModel { private MutableLiveData<Integer> imgLocalResId; private MutableLiveData<String> imgUrl; public MutableLiveData<Integer> getImgLocalResId() { if (imgLocalResId==null){ imgLocalResId = new MutableLiveData<>(); imgLocalResId.setValue(R.mipmap.idol); } return imgLocalResId; } public MutableLiveData<String> getImgUrl() { if (imgUrl==null){ imgUrl = new MutableLiveData<>(); imgUrl.setValue( "http://wx1.sinaimg.cn/mw2000/007fS0GEgy1gs59xp5cwfj60tw1a810v02.jpg" ); } return imgUrl; } }
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //创建databinding对象 ActivityMainBinding activityMainBinding = DataBindingUtil.setContentView(this,R.layout.activity_main); //获取ViewModel对象 MyViewModel myViewModel = new ViewModelProvider(this).get(MyViewModel.class); //设置dataBinding的变量的值 activityMainBinding.setViewModel(myViewModel); //不设置无法实现单向绑定 activityMainBinding.setLifecycleOwner(this); } }