当前位置: 首页 > news >正文

这一篇Databinding应该可以帮助迅速上手吧

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" />
<!--      <variable-->
<!--           name="starUtil"-->
<!--            type="com.dongnaoedu.databinding.StarUtils" />-->
<!--        使用静态类的方法可以直接import然后使用 而不需要在activity里面setXXX--><import type="com.dongnaoedu.databinding.StarUtils" />
</data>

variable标签携带的是数据,而import标签则可以引入静态方法

导入数据后就可以使用数据了,在xml中使用 "@{}"的格式去赋值,或者使用工具类`

例如:

<?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"><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" />
<!--      <variable-->
<!--           name="starUtil"-->
<!--            type="com.dongnaoedu.databinding.StarUtils" />-->
<!--        使用静态类的方法可以直接import然后使用 而不需要在activity里面setXXX--><import type="com.dongnaoedu.databinding.StarUtils" />
</data>
</layout>

注意,使用variable还需要在java代码中为binding对象传入数据:

public class MainActivity extends AppCompatActivity {@Overrideprotected 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;}//回调方法,一个参数且为Viewpublic 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的属性时

例如:

     <TextViewandroid: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时

     <Buttonandroid:id="@+id/button2"android:text="@{textView2.text}"/><!--    button2的text使用了上面id为textView2的text -->

4. 将variable值传入给include包含的子布局时:(前提是variable的type类型一致)

例如:子布局 sub

 <data><variablename="sub"type="com.dongnaoedu.databinding2.Idol" /></data>

父布局:

 <data><variablename="idol"type="com.dongnaoedu.databinding2.Idol" /></data>

在父布局中将 idol 传给 子布局的sub

     <includelayout="@layout/sub"app:sub="@{idol}"/>

5. 设置BindingAdapter

例如:为imageview设置图片值

<?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="networkImage"type="String" /><variablename="localImage"type="int" /></data><androidx.constraintlayout.widget.ConstraintLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><ImageViewandroid: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><variablename="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文件:

<?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"><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上)}
}

在这里插入图片描述

其他用法:前往官网

相关文章:

这一篇Databinding应该可以帮助迅速上手吧

Databinding使用篇&#xff08;迅速上手&#xff09; 使用前需要在模块级别的build.gradle里面的android闭包里添加&#xff1a; dataBinding{enabled true}接着在layout文件中按下Alt 回车&#xff0c; 将布局转换成data binding layout即可&#xff0c;此时编译就会生成对…...

【PHP在线定制商城网站源码V3.0】开源的DIY在线定制商城系统+在线礼品定制

源码下载&#xff1a;https://download.csdn.net/download/m0_66047725/87637177 PHP在线定制商城网站源码&#xff0c;免费开源、免费下载。本商城基于mycncart开发。安装成功后即可浏览&#xff0c;你可以在后台->安装扩展功能上传安装插件&#xff0c;在代码调整中点击刷…...

cout源码浅析

目录 cout源码浅析 那么对于没有定义在这之中的要怎么办呢&#xff1f; 实际使用 结语 首先来看我从cplusplus中截取的这张图&#xff1a; 注意最下面这一行字。cout其实是ostream的一个标准对象object。而上面则演示了一些继承关系。 好的&#xff0c;理解了之后&#xf…...

发送Ajax get请求详解

发送AJAX get请求&#xff0c;前端代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8"> <title>ajax get请求</title> </head> <body> <script type"text/java…...

SQL语句

创建及删除数据库和表 CREATE DATABASE 数据库名; CREATE DATABASE school; 创建新的表 CREATE TABLE 表名(字段1 数据类型,字段2 数据类型[,...] [,PRIMARY KEY (主键名)]); #主键一般选择能代表唯一性的字段&#xff0c;不允许取空值(NULL)&#xff0c;值也不允许重复&…...

Mysql 学习(八)单表查询方法二

复杂查询 上一节说了5种访问类型的查询&#xff0c;这一节就来说说关于这些比较复杂的查询 情况一&#xff1a;多个二级索引查询 sql&#xff1a;SELECT * FROM index_value_table WHERE value1 abc AND value2 > 1000;搜索条件&#xff1a; value1 等于 abcvalue2 大于…...

安卓系统下的截屏和录屏

可以抓取手机屏幕画面&#xff08;屏幕截图&#xff09;&#xff0c;也可以录制屏幕画面视频。拍摄屏幕后&#xff0c;可以查看、编辑和分享所拍的图片或视频。 抓取屏幕截图 打开要抓取的屏幕。视手机情况执行下列一个操作&#xff0c;3种方法看你手机有效的&#xff1a; 同…...

行为型模式-中介者模式

中介者模式 概述 一般来说&#xff0c;同事类之间的关系是比较复杂的&#xff0c;多个同事类之间互相关联时&#xff0c;他们之间的关系会呈现为复杂的网状结构&#xff0c;这是一种过度耦合的架构&#xff0c;即不利于类的复用&#xff0c;也不稳定。例如在下左图中&#xf…...

辅助驾驶功能开发-功能规范篇(16)-2-领航辅助系统NAP-功能ODD定义

1.系统定义 智能驾驶系统包含行车场景功能和泊车场景功能,行车场景功能包括安全ADAS功能、基础ADAS功能和高阶ADAS功能三大类,本文档定义高阶ADAS功能中的导航辅助驾驶功能用例。 1.1.高阶ADAS功能列表 功能需求ID 功能分类 功能名称...

PMP/高项 06-项目成本管理

项目成本管理 概念 项目成本管理 项目成本管理又被称为项目造价管理&#xff0c;是有关项目成本和项目价值两个方面的管理&#xff0c;是为保障以最小的成本实现最大的项目价值而开展的项目专项管理工作。 确保在批准的项目预算内完成项目 成本管理内容 规划成本管理 制定项目…...

XXL-JOB中间件【实现分布式任务调度】

目录 1&#xff1a;XXL-JOB介绍 2&#xff1a;搭建XXL-JOB 2.1&#xff1a;调度中心 2.2&#xff1a;执行器 2.3&#xff1a;执行任务 3&#xff1a;分片广播 1&#xff1a;XXL-JOB介绍 XXL-JOB是一个轻量级分布式任务调度平台&#xff0c;其核心设计目标是开发迅速、学…...

Vue3+Element Plus环境搭建和一键切换明暗主题的配置

Vue (发音为 /vjuː/&#xff0c;类似 view) 是一款用于构建用户界面的 JavaScript 框架。而Element Plus是一款基于Vue3面向设计师和开发者的组件库。 最终效果&#xff1a; 环境搭建 已安装 16.0 或更高版本的 Node.js&#xff0c;终端&#xff1a; npm init vuelatest这一…...

Leetcode326. 3 的幂

Every day a leetcode 题目来源&#xff1a;326. 3 的幂 相似题目&#xff1a;342. 4的幂 解法1&#xff1a;递归 代码&#xff1a; /** lc appleetcode.cn id326 langcpp** [326] 3 的幂*/// lc codestart class Solution { public:bool isPowerOfThree(int n){if (n <…...

【运动规划算法项目实战】如何在栅格地图中实现Dijkstra算法

文章目录 简介一、算法介绍1.1 Dijkstra算法流程1.2 Dijkstra算法伪代码二、代码实现2.1 ROS实现2.2 RVIZ演示三、总结简介 Dijkstra算法是一种用于图中单源最短路径的贪心算法。在计算机科学和网络设计中广泛应用。该算法从起点开始,通过优先选择距离起点最近的未标记节点来…...

【算法】一文彻底搞懂ZAB算法

文章目录 什么是ZAB 算法&#xff1f;深入ZAB算法1. 消息广播两阶段提交ZAB消息广播过程 2. 崩溃恢复选举参数选举流程 ZAB算法需要解决的两大问题1. 已经被处理的消息不能丢2. 被丢弃的消息不能再次出现 最近需要设计一个分布式系统&#xff0c;需要一个中间件来存储共享的信息…...

【软考高级】2022年系统分析师综合知识

1.( )是从系统的应用领域而不是从系统用户的特定需要中得出的&#xff0c;它们可以是新的功能性需求&#xff0c;或者是对已有功能性需求的约束&#xff0c;或者是陈述特定的计算必须遵守的要求。 A.功能性需求 B. 用户需求 C.产品需求 D.领域需求 2.对于安全关键系…...

关于AI未来的思考和应用场景

关于AI未来的思考和应用场景 AI&#xff08;人工智能&#xff09;是当今最热门的技术领域之一&#xff0c;它已经在多个领域产生了深远的影响&#xff0c;如医疗、金融、制造业等。未来&#xff0c;AI将继续发展&#xff0c;并在更多领域产生重要的影响。 AI的未来发展方向有…...

智慧城市规划数字化管理:数字孪生技术的创新应用

随着智能城市的不断发展&#xff0c;数字孪生技术也开始在智慧城市的建设中得到了广泛应用。数字孪生作为一种数字化的复制技术&#xff0c;它可以模拟真实世界中的实体和过程。 在城市规划方面&#xff0c;数字孪生可以帮助城市规划师更加直观地了解城市的整体规划和发展趋势&…...

开心档之C++ 指针

C 指针 学习 C 的指针既简单又有趣。通过指针&#xff0c;可以简化一些 C 编程任务的执行&#xff0c;还有一些任务&#xff0c;如动态内存分配&#xff0c;没有指针是无法执行的。所以&#xff0c;想要成为一名优秀的 C 程序员&#xff0c;学习指针是很有必要的。 正如您所知…...

零基础搭建私人影音媒体平台【远程访问Jellyfin播放器】

文章目录 1. 前言2. Jellyfin服务网站搭建2.1. Jellyfin下载和安装2.2. Jellyfin网页测试 3.本地网页发布3.1 cpolar的安装和注册3.2 Cpolar云端设置3.3 Cpolar本地设置 4.公网访问测试5. 结语 转载自内网穿透工具的文章&#xff1a;零基础搭建私人影音媒体平台【远程访问Jelly…...

Vim 调用外部命令学习笔记

Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...

谷歌浏览器插件

项目中有时候会用到插件 sync-cookie-extension1.0.0&#xff1a;开发环境同步测试 cookie 至 localhost&#xff0c;便于本地请求服务携带 cookie 参考地址&#xff1a;https://juejin.cn/post/7139354571712757767 里面有源码下载下来&#xff0c;加在到扩展即可使用FeHelp…...

springboot 百货中心供应链管理系统小程序

一、前言 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;百货中心供应链管理系统被用户普遍使用&#xff0c;为方…...

ES6从入门到精通:前言

ES6简介 ES6&#xff08;ECMAScript 2015&#xff09;是JavaScript语言的重大更新&#xff0c;引入了许多新特性&#xff0c;包括语法糖、新数据类型、模块化支持等&#xff0c;显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var&#xf…...

树莓派超全系列教程文档--(62)使用rpicam-app通过网络流式传输视频

使用rpicam-app通过网络流式传输视频 使用 rpicam-app 通过网络流式传输视频UDPTCPRTSPlibavGStreamerRTPlibcamerasrc GStreamer 元素 文章来源&#xff1a; http://raspberry.dns8844.cn/documentation 原文网址 使用 rpicam-app 通过网络流式传输视频 本节介绍来自 rpica…...

视频字幕质量评估的大规模细粒度基准

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用&#xff0c;因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型&#xff08;VLMs&#xff09;在字幕生成方面…...

【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统

目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索&#xff08;基于物理空间 广播范围&#xff09;2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...

什么是Ansible Jinja2

理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具&#xff0c;可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板&#xff0c;允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板&#xff0c;并通…...

【Java学习笔记】BigInteger 和 BigDecimal 类

BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点&#xff1a;传参类型必须是类对象 一、BigInteger 1. 作用&#xff1a;适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...

智能职业发展系统:AI驱动的职业规划平台技术解析

智能职业发展系统&#xff1a;AI驱动的职业规划平台技术解析 引言&#xff1a;数字时代的职业革命 在当今瞬息万变的就业市场中&#xff0c;传统的职业规划方法已无法满足个人和企业的需求。据统计&#xff0c;全球每年有超过2亿人面临职业转型困境&#xff0c;而企业也因此遭…...