Databinding使用篇(迅速上手)
使用前需要在模块级别的build.gradle里面的android闭包里添加:
dataBinding{enabled = true}
接着在layout文件中按下Alt + 回车, 将布局转换成data binding layout即可,此时编译就会生成对应的Binding java类
layout文件命名为xxx_xxx.xml生成的java类命名格式为XxxXxxBinding.java
例如:activity_main.xml --> ActivityMainBinding.java
常见使用:
1. 赋值 (variable的种类有很多种,View,基本类型,引用类型等各种各样的)
在xml的 标签下添加标签,写入对应的数据名,以及数据类型
<data><variablename="test"type="com.dongnaoedu.databinding.Idol" /><variablename="eventHandle"type="com.dongnaoedu.databinding.EventHandleListener" /><!-- <import type="com.dongnaoedu.databinding.StarUtils" /></data>
variable标签携带的是数据,而import标签则可以引入静态方法
导入数据后就可以使用数据了,在xml中使用 “@{}”的格式去赋值,或者使用工具类`
例如:
<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"><androidx.constraintlayout.widget.ConstraintLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><ImageViewandroid:id="@+id/imageView"android:layout_width="300dip"android:layout_height="300dip"android:src="@drawable/wangzhai"app:layout_constraintBottom_toTopOf="@+id/guideline"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintHorizontal_bias="0.495"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent"app:layout_constraintVertical_bias="0.803"tools:srcCompat="@tools:sample/avatars" /><TextViewandroid:id="@+id/textView"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@{test.name}"android:textSize="24sp"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="@+id/guideline"app:layout_constraintVertical_bias="0.176"tools:text="姓名" /><TextViewandroid:id="@+id/textView2"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="48dp"android:text="@{eventHandle.getStar(test.star)}"android:textSize="18sp"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintHorizontal_bias="0.498"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toBottomOf="@+id/textView"tools:text="五星" /><androidx.constraintlayout.widget.Guidelineandroid:id="@+id/guideline"android:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="horizontal"app:layout_constraintGuide_percent="0.5" /><Buttonandroid:id="@+id/button2"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginBottom="60dp"android:text="喜欢"android:onClick="@{()->eventHandle.buttonOnClick()}"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintHorizontal_bias="0.498"app:layout_constraintStart_toStartOf="parent" /></androidx.constraintlayout.widget.ConstraintLayout><data><variablename="test"type="com.dongnaoedu.databinding.Idol" /><variablename="eventHandle"type="com.dongnaoedu.databinding.EventHandleListener" /><!-- <import type="com.dongnaoedu.databinding.StarUtils" /></data></layout>
注意,使用variable还需要在java代码中为binding对象传入数据:
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ActivityMainBinding activityMainBinding = DataBindingUtil.setContentView(this,R.layout.activity_main); Idol idol = new Idol("旺仔",5); activityMainBinding.setTest(idol); //为binding设置数据 activityMainBinding.setEventHandle(new EventHandleListener(this));//为binding设置数据 }}
2. 在xml设置点击回调方法
当回调方法中参数只有一个且为View时:
public class EventHandleListener { private Context context; public EventHandleListener(Context context) { this.context = context; } //回调方法,一个参数且为View public void buttonOnClick(View view){ Toast.makeText(context,"喜欢 ",Toast.LENGTH_SHORT).show(); }}
使用:xxx类名.xxx方法名
android:onClick="@{eventHandle.buttonOnClick}"
回调方法为其他类型时:
public class EventHandleListener { private Context context; public EventHandleListener(Context context) { this.context = context; } //回调方法使用没有带View的参数时 public void buttonOnClick(int data,String name){ Toast.makeText(context,"喜欢" + data + " "+name,Toast.LENGTH_SHORT).show(); }}
使用:()->xxx类名.xxx方法名(参数)
xxxxxxxxxx android:onClick="@{()->eventHandle.buttonOnClick(1,test.name)}"
当然也可以写成:
android:onClick="@{(view)->eventHandle.buttonOnClick(1,test.name)}"
只不过此处的view可以忽略不写,但俩种方式都是一样的
因为onclick方法的参数是(View view),所以在回调方法需要传入View对象的时候,我们可以这样子
public class EventHandleListener { private Context context; public EventHandleListener(Context context) { this.context = context; } public void buttonOnClick(View view,int data,String name){ Toast.makeText(context,"喜欢" + data + " "+name,Toast.LENGTH_SHORT).show(); }}
使用:
android:onClick="@{(theview)->eventHandle.buttonOnClick(theview,1,test.name)}"
上述也是通过lambda表达式将onclick的参数view传入到我们的回调方法中
3. 属性值使用其他view的属性时
例如:
<TextView android:id="@+id/textView2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="48dp" android:text="@{StarUtils.getStar(test.star)}" android:textSize="18sp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.498" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/textView" tools:text="五星" />
我要使用上面 id = textView2的text时
<Button android:id="@+id/button2" android:text="@{textView2.text}"/>
4. 将variable值传入给include包含的子布局时:(前提是variable的type类型一致)
例如:子布局 sub
<data> <variable name="sub" type="com.dongnaoedu.databinding2.Idol" /> </data>
父布局:
<data> <variable name="idol" type="com.dongnaoedu.databinding2.Idol" /> </data>
在父布局中将 idol 传给 子布局的sub
<include layout="@layout/sub" app:sub="@{idol}"/>
5. 设置BindingAdapter
例如:为imageview设置图片值
<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="networkImage" type="String" /> <variable name="localImage" type="int" /> </data> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <ImageView android:id="@+id/imageView" app:image="@{networkImage}" app:defaultImageResource="@{localImage}" android:layout_width="300dip" android:layout_height="300dip" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" tools:srcCompat="@tools:sample/avatars" /> </androidx.constraintlayout.widget.ConstraintLayout></layout>
写个adapter的java类:
public class ImageViewBindingAdapter { /** 1.如果重载方法有多个参数的,会优先调用多个参数的 2.优先级:(1)Picasso.get().load(url).placeholder(R.drawable.ic_launcher_background).into(imageView); * (2)优先级是大于imageView.setImageResource(resId); * 即 使用(1)加载图片后,再使用(2)也无法改变图片内容 *///加载网络图片@BindingAdapter("image")public static void setImage(ImageView imageView, String url){Log.d("ning", "setImage: "+ "我是网络图片");if(!TextUtils.isEmpty(url)){Picasso.get().load(url).placeholder(R.drawable.ic_launcher_background).into(imageView);}else{imageView.setBackgroundColor(Color.GRAY);}}//加载本地图片@BindingAdapter("defaultImageResource")public static void setImage(ImageView imageView, int resId){Log.d("ning", "setImage: "+ "我是本地图片");imageView.setImageResource(resId);}////参数可选,网络图片为空时,加载本地图片@BindingAdapter(value = {"image", "defaultImageResource"}, requireAll = false)public static void setImage(ImageView imageView, String url, int resId){Log.d("ning", "setImage: "+ "我是本地+网络图片");if(!TextUtils.isEmpty(url)){Picasso.get().load(url).placeholder(R.drawable.ic_launcher_background).into(imageView);}else{imageView.setImageResource(resId);}}}
记得给binding类传入值:
public class MainActivity extends AppCompatActivity {String TAG = "ning";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);Log.d(TAG, "onCreate: ");ActivityMainBinding activityMainBinding = DataBindingUtil.setContentView(this,R.layout.activity_main);activityMainBinding.setLocalImage(R.drawable.wangzhai);activityMainBinding.setNetworkImage(networkUrl);}}
6.双向绑定-- ObservableField
双向绑定在xml中要区别于赋值,赋值是"@{}", 而双向绑定是"@={}"
用法举例:
存放observableField数据的类:
public class UserViewModel{public ObservableField<User> userObservableField;public UserViewModel(){User user = new User("Jack");userObservableField = new ObservableField<>();userObservableField.set(user);Log.d("TAG", "InitchangeValue: " + userObservableField.get());}}
user类:
public class User {private String userName;public String getUserName() {return userName;}public void setUserName(String userName) {this.userName = userName;}public User(String userName) {this.userName = userName;}}
使用:
xml中editText:
<?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><variablename="userViewModel"type="com.dongnaoedu.databinding5.UserViewModel" /></data><androidx.constraintlayout.widget.ConstraintLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><EditTextandroid:id="@+id/editText"android:layout_width="wrap_content"android:layout_height="wrap_content"android:ems="10"android:inputType="textPersonName"android:text="@={userViewModel.userObservableField.userName}"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent" /><Buttonandroid:id="@+id/button"android:onClick="changeValue"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="chageValue"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toBottomOf="@+id/editText" /></androidx.constraintlayout.widget.ConstraintLayout></layout>
注意上面直接是 android:text="@={userViewModel.userObservableField.userName}", 因为默认是调用getUserName()了。
java代码中:
public class MainActivity extends AppCompatActivity {UserViewModel viewModel;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);ActivityMainBinding activityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);viewModel = new UserViewModel();activityMainBinding.setUserViewModel(viewModel); //为binding设置值//开启一个定时任务在java代码中改变user的usernamenew Timer().schedule(new TimerTask() {@Overridepublic void run() {for(int i = 0; i < 3; i++){try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}User user = (User)viewModel.userObservableField.get();user.setUserName(String.valueOf(i));viewModel.userObservableField.notifyChange();//一定要调用notifyChange()方法通知属性值改变了}}},2000);}/** * button的回调方法,用来测试值是否有双线绑定 * @param view */public void changeValue(View view) {User user = (User)viewModel.userObservableField.get();Log.d("TAG", "changeValue: " + viewModel.userObservableField.get() + " " + user.getUserName());}}
运行后发现-- 在java代码中改变user的username都会反馈到UI上,在editText中随便输入,都会改变user的username值,做到了数据和UI间的双向绑定。
7 双向绑定BaseObservable的使用
1. 写个类继承BaseObservable,并给所要使用双向绑定的成员变量添加getter和setter方法
2. getter方法要加上@Bindable, 加上后才会生成对应的字段的BR字段
3. 在setter中调用notifyPropertyChanged(BR.xxx) 去通知对应数据改变了
4. 在xml中要用 “@={xxx.xxx}”的形式。
android:text="@={fileViewModel.cacheGenerateSize}"
使用
写类对象,并提供对应的getter和setter方法。 以及为getter方法打上@Bindable注解,setter方法调用notifyPropertyChanged()
public class FileViewModel extends BaseObservable {private String systemTotalSpace= ""; //系统的总存储空间, MB@Bindablepublic String getSystemTotalSpace() {return systemTotalSpace;}public void setSystemTotalSpace(String systemTotalSpace) {if(systemTotalSpace != null && !systemTotalSpace.equals(this.systemTotalSpace)){this.systemTotalSpace = systemTotalSpace;notifyPropertyChanged(BR.systemTotalSpace);}}
在xml中:传入对应值
<data> <variable name="fileViewModel" type="net.sunniwell.fileautobuilder.FileViewModel" /></data>
<TextViewandroid:id="@+id/tv_system_total_space"android:layout_gravity="end"android:layout_width="wrap_content"android:layout_height="wrap_content"android:gravity="center"android:text="@={fileViewModel.systemTotalSpace}"android:textColor="#60acfc"android:textSize="20sp"android:layout_marginBottom="5dp" />
在java代码中将fileViewModel对象传入给打他binding
fileViewModel.setSystemTotalSpace(" " + Constraint.SYSTEM_TOTAL_SPACE + "MB");mbind.setFileViewModel(fileViewModel);
java代码中要改变值时,直接调用fileviewmodel.setxxx()即可
8. databinding结合viewmodel以及livedata
结合livedata只需要加上:
activityMainBinding.setLifecycleOwner(this);
使用举例(简单记分牌)
viewmodel:
public class MyViewModel extends ViewModel {private MutableLiveData<Integer> aTeamScore;private MutableLiveData<Integer> bTeamScore;private Integer aLast;private Integer bLast;public MutableLiveData<Integer> getaTeamScore() {if(aTeamScore == null){aTeamScore = new MutableLiveData<>();aTeamScore.setValue(0);}return aTeamScore;}public MutableLiveData<Integer> getbTeamScore() {if(bTeamScore == null){bTeamScore = new MutableLiveData<>();bTeamScore.setValue(0);}return bTeamScore;}public void aTeamAdd(int i){saveLastScore();aTeamScore.setValue(aTeamScore.getValue() + i);}public void bTeamAdd(int i){saveLastScore();bTeamScore.setValue(bTeamScore.getValue() + i);}public void undo(){aTeamScore.setValue(aLast);bTeamScore.setValue(bLast);}public void reset(){aTeamScore.setValue(0);bTeamScore.setValue(0);}//记录上一次的分数private void saveLastScore(){this.aLast = aTeamScore.getValue();this.bLast = bTeamScore.getValue();}}
layout文件:
<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"><androidx.constraintlayout.widget.ConstraintLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><Buttonandroid:id="@+id/button1"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_margin="8dp"android:background="@android:color/holo_red_light"android:onClick="@{()->viewModel.aTeamAdd(1)}"android:shadowColor="@android:color/background_light"android:text="@string/button1"android:textColor="#FFFFFF"app:layout_constraintBottom_toTopOf="@+id/guideline9"app:layout_constraintEnd_toStartOf="@+id/guideline3"app:layout_constraintHorizontal_bias="0.423"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="@+id/guideline8"app:layout_constraintVertical_bias="0.564" /><Buttonandroid:id="@+id/button4"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_margin="8dip"android:background="@color/colorAccent"android:onClick="@{()->viewModel.bTeamAdd(1)}"android:shadowColor="@android:color/background_light"android:text="@string/button1"android:textColor="#FFFFFF"app:layout_constraintBottom_toTopOf="@+id/guideline9"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintHorizontal_bias="0.0"app:layout_constraintStart_toStartOf="@+id/guideline3"app:layout_constraintTop_toTopOf="@+id/guideline8"app:layout_constraintVertical_bias="0.564" /><Buttonandroid:id="@+id/button2"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_margin="8dp"android:background="@android:color/holo_red_light"android:onClick="@{()->viewModel.aTeamAdd(2)}"android:shadowColor="@android:color/background_light"android:text="@string/button2"android:textColor="#FFFFFF"app:layout_constraintBottom_toTopOf="@+id/guideline10"app:layout_constraintEnd_toStartOf="@+id/guideline3"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="@+id/guideline9" /><Buttonandroid:id="@+id/button3"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_margin="8dp"android:background="@android:color/holo_red_light"android:onClick="@{()->viewModel.aTeamAdd(3)}"android:shadowColor="@android:color/background_light"android:text="@string/button3"android:textColor="#FFFFFF"app:layout_constraintBottom_toTopOf="@+id/guideline11"app:layout_constraintEnd_toStartOf="@+id/guideline3"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="@+id/guideline10" /><Buttonandroid:id="@+id/button6"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_margin="8dp"android:background="@color/colorAccent"android:onClick="@{()->viewModel.bTeamAdd(3)}"android:shadowColor="@android:color/background_light"android:text="@string/button3"android:textColor="#FFFFFF"app:layout_constraintBottom_toTopOf="@+id/guideline11"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="@+id/guideline3"app:layout_constraintTop_toTopOf="@+id/guideline10" /><Buttonandroid:id="@+id/button5"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_margin="8dp"android:background="@color/colorAccent"android:onClick="@{()->viewModel.bTeamAdd(2)}"android:shadowColor="@android:color/background_light"android:text="@string/button2"android:textColor="#FFFFFF"app:layout_constraintBottom_toTopOf="@+id/guideline10"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="@+id/guideline3"app:layout_constraintTop_toTopOf="@+id/guideline9" /><ImageButtonandroid:id="@+id/imageButton"android:layout_width="wrap_content"android:layout_height="wrap_content"android:contentDescription="@string/undoButton"android:onClick="@{()->viewModel.undo()}"app:layout_constraintBottom_toTopOf="@+id/guideline12"app:layout_constraintEnd_toStartOf="@+id/guideline3"app:layout_constraintHorizontal_bias="0.8"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="@+id/guideline11"app:srcCompat="@drawable/ic_undo_black_24dp" /><ImageButtonandroid:id="@+id/imageButton2"android:layout_width="wrap_content"android:layout_height="wrap_content"android:contentDescription="@string/resetButton"android:onClick="@{()->viewModel.reset()}"app:layout_constraintBottom_toTopOf="@+id/guideline12"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintHorizontal_bias="0.2"app:layout_constraintStart_toStartOf="@+id/guideline3"app:layout_constraintTop_toTopOf="@+id/guideline11"app:srcCompat="@drawable/ic_refresh_black_24dp" /><TextViewandroid:id="@+id/textView1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Team A"android:textSize="@dimen/teamTextSize"app:layout_constraintBottom_toTopOf="@+id/guideline7"app:layout_constraintEnd_toStartOf="@+id/guideline3"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="@+id/guideline2" /><TextViewandroid:id="@+id/textView2"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Team B"android:textSize="@dimen/teamTextSize"app:layout_constraintBottom_toTopOf="@+id/guideline7"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="@+id/guideline3"app:layout_constraintTop_toTopOf="@+id/guideline2" /><TextViewandroid:id="@+id/scoreA"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@{String.valueOf(viewModel.getaTeamScore())}"android:textColor="@android:color/holo_red_light"android:textSize="@dimen/scoreTextSize"app:layout_constraintBottom_toTopOf="@+id/guideline8"app:layout_constraintEnd_toStartOf="@+id/guideline3"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="@+id/guideline7"tools:text="120" /><TextViewandroid:id="@+id/scoreB"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@{String.valueOf(viewModel.getbTeamScore())}"android:textColor="@color/colorAccent"android:textSize="@dimen/scoreTextSize"app:layout_constraintBottom_toTopOf="@+id/guideline8"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="@+id/guideline3"app:layout_constraintTop_toTopOf="@+id/guideline7"tools:text="100" /><androidx.constraintlayout.widget.Guidelineandroid:id="@+id/guideline2"android:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="horizontal"app:layout_constraintGuide_percent="0.05" /><androidx.constraintlayout.widget.Guidelineandroid:id="@+id/guideline3"android:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="vertical"app:layout_constraintGuide_percent="0.5" /><androidx.constraintlayout.widget.Guidelineandroid:id="@+id/guideline4"android:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="vertical"app:layout_constraintGuide_end="-220dp" /><androidx.constraintlayout.widget.Guidelineandroid:id="@+id/guideline7"android:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="horizontal"app:layout_constraintGuide_percent="0.15" /><androidx.constraintlayout.widget.Guidelineandroid:id="@+id/guideline8"android:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="horizontal"app:layout_constraintGuide_percent="0.35" /><androidx.constraintlayout.widget.Guidelineandroid:id="@+id/guideline9"android:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="horizontal"app:layout_constraintGuide_percent="0.5" /><androidx.constraintlayout.widget.Guidelineandroid:id="@+id/guideline10"android:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="horizontal"app:layout_constraintGuide_percent="0.65" /><androidx.constraintlayout.widget.Guidelineandroid:id="@+id/guideline11"android:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="horizontal"app:layout_constraintGuide_percent="0.8" /><androidx.constraintlayout.widget.Guidelineandroid:id="@+id/guideline12"android:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="horizontal"app:layout_constraintGuide_percent="0.9" /></androidx.constraintlayout.widget.ConstraintLayout><data><variablename="viewModel"type="com.dongnaoedu.databinding7.MyViewModel" /></data></layout>
使用:
public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);ActivityMainBinding activityMainBinding = DataBindingUtil.setContentView(this,R.layout.activity_main);MyViewModel viewModel = new ViewModelProvider(this, new ViewModelProvider.AndroidViewModelFactory(getApplication())).get(MyViewModel.class);activityMainBinding.setViewModel(viewModel);activityMainBinding.setLifecycleOwner(this); //一定要加入这个,否则livedata无效(改变了livedata的值也反馈不到UI上)}}