DataBinding库简化了UI与数据源之间的绑定过程,提高了开发效率。
一、DataBinding简介
DataBinding 是一种用于在安卓应用中实现简洁、高效的数据绑定的库。它使开发者能够以声明性的方式将 UI 组件与数据源进行绑定,从而自动更新界面上的数据,并简化了与 UI 相关的代码编写过程。
设置 Data Binding
要使用 Data Binding,需要进行以下设置:
1. 在 app 模块的 build.gradle 文件中启用 Data Binding:
android { ... dataBinding { enabled = true } }
2. 在布局文件顶部添加 <layout>
标签来包裹布局内容:
<layout xmlns:android="http://schemas.android.com/apk/res/android"> <!-- 布局内容 --> </layout>
3. 在 Activity 或 Fragment 中获取绑定的实例:
// 在 Activity 中通过 setContentView 方法绑定布局 MyLayoutBinding binding = DataBindingUtil.setContentView(this, R.layout.my_layout); // 在 Fragment 中通过 LayoutInflater 绑定布局 MyLayoutBinding binding = MyLayoutBinding.inflate(inflater, container, false);
数据绑定表达式
可以在布局文件中使用表达式语言来引用绑定的数据和执行操作,例如:
引用变量或对象属性:
<TextView android:text="@{user.name}" ... />
执行方法调用:
<Button android:onClick="@{onClickListener.onButtonClick()}" ... />
使用条件语句和循环:
<TextView android:text="@{user.isAdult ? `Adult` : `Child`}" ... /> <LinearLayout android:visibility="@{user.isAdmin ? View.VISIBLE : View.GONE}" ... /> <RecyclerView app:itemList="@{list}" ... />
双向绑定
双向绑定是一种数据绑定的概念,它使得视图(UI)和数据模型(Model)之间能够自动保持同步。当一个变量在视图中改变时,相关联的数据模型也会更新;反之,当数据模型的值发生变化时,视图也会相应地更新。
DataBinding 还支持双向绑定,即将 UI 组件的变化反映到数据源中。可以通过 @=
符号实现双向绑定:
<EditText android:text="@={user.name}" ... />
二、例子
例1:DataBinding实现文本绑定和点击事件
MainActivity :
package com.example.databinding2; import androidx.appcompat.app.AppCompatActivity; import androidx.databinding.DataBindingUtil; import android.os.Bundle; import com.example.databinding2.databinding.ActivityMainBinding; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ActivityMainBinding mainBinding = DataBindingUtil.setContentView(this,R.layout.activity_main); // 利用DataBinding绑定UI文本 Food food = new Food("麻辣烫", (float) 4); // 利用DataBinding实现点击事件 mainBinding.setOnClickListener(new OnClickListener(this)); mainBinding.setFood(food); } }
CountStart :
package com.example.databinding2; public class CountStart { public static String getStar(float star){ return star +"星"; } }
Food:
package com.example.databinding; public class Food { public String name; public float star; public Food(String name,float star){ this.name = name; this.star = star; } }
OnClickListener :
package com.example.databinding2; import android.content.Context; import android.view.View; import android.widget.Toast; public class OnClickListener { private Context mContext; public OnClickListener(Context context){ mContext = context; } public void buttonOnClick(View view){ Toast.makeText(mContext, "点击了提交!", Toast.LENGTH_SHORT).show(); } }
activity_main:
<?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 = "com.example.databinding2.CountStart"/> <variable name="Food" type="com.example.databinding2.Food" /> <!-- 实现点击事件 --> <variable name="OnClickListener" type="com.example.databinding2.OnClickListener" /> </data> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <androidx.constraintlayout.widget.Guideline android:id="@+id/guideline2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" app:layout_constraintGuide_begin="365dp" /> <ImageView android:src="@drawable/img" android:id="@+id/imageView" android:layout_width="300dp" android:layout_height="300dp" app:layout_constraintBottom_toTopOf="@+id/guideline2" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.497" tools:srcCompat="@tools:sample/avatars" /> <RatingBar android:id="@+id/ratingBar" android:layout_width="244dp" android:layout_height="54dp" android:max="5" android:rating="@{Food.star}" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="@+id/guideline2" app:layout_constraintVertical_bias="0.079" /> <TextView android:id="@+id/textView" android:layout_width="129dp" android:layout_height="28dp" android:text="@{Food.name}" android:textSize="20sp" app:layout_constraintBottom_toTopOf="@+id/ratingBar" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.673" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.917" /> <Button android:onClick="@{OnClickListener.buttonOnClick}" android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="160dp" android:text="提交" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.498" app:layout_constraintStart_toStartOf="parent" /> <TextView android:id="@+id/textView2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{CountStart.getStar(Food.star)}" android:textSize="25sp" app:layout_constraintBottom_toTopOf="@+id/button" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/ratingBar" /> </androidx.constraintlayout.widget.ConstraintLayout> </layout>
build.gradle:
android { compileSdk 32 defaultConfig { applicationId "com.example.databinding" minSdk 21 targetSdk 32 versionCode 1 versionName "1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" dataBinding { enabled = true } }
运行结果:
例二:二级界面的绑定
activity_main:
<?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 = "com.example.databinding2.CountStart"/> <variable name="Food" type="com.example.databinding2.Food" /> <!-- 实现点击事件 --> <variable name="OnClickListener" type="com.example.databinding2.OnClickListener" /> </data> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <androidx.constraintlayout.widget.Guideline android:id="@+id/guideline2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" app:layout_constraintGuide_begin="365dp" /> <ImageView android:src="@drawable/img" android:id="@+id/imageView" android:layout_width="300dp" android:layout_height="300dp" app:layout_constraintBottom_toTopOf="@+id/guideline2" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.497" tools:srcCompat="@tools:sample/avatars" /> <TextView android:id="@+id/textView" android:layout_width="129dp" android:layout_height="28dp" android:text="@{Food.name}" android:textSize="20sp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.673" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <include app:Food="@{Food}" app:OnClickListener="@{OnClickListener}" layout="@layout/sub_main" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="8dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.497" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="@+id/guideline2" app:layout_constraintVertical_bias="0.253" /> </androidx.constraintlayout.widget.ConstraintLayout> </layout>
sub_main:
<?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="Food" type="com.example.databinding2.Food" /> <!-- 实现点击事件 --> <variable name="OnClickListener" type="com.example.databinding2.OnClickListener" /> </data> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <RatingBar android:id="@+id/ratingBar2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:rating="@{Food.star}" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.438" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.065" /> <TextView android:id="@+id/textView3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="32dp" android:text="@{Food.name}" android:textSize="25sp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.449" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/ratingBar2" /> <Button android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="24dp" android:text="提交" android:onClick="@{OnClickListener.buttonOnClick}" android:textSize="20sp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.463" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/textView3" /> </androidx.constraintlayout.widget.ConstraintLayout> </layout>
其他代码和运行效果跟例一一样。
例三、双向绑定例子
MainActivity:
public class MainActivity extends AppCompatActivity { private ViewModel viewModel; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 使用DataBindingUtil进行绑定 ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main); // 初始化ViewModel viewModel = new ViewModel(); // 设置ViewModel到绑定对象中 binding.setViewModel(viewModel); } }
ViewModel :
public class ViewModel extends BaseObservable { private String inputText; @Bindable public String getInputText() { return inputText; } public void setInputText(String inputText) { this.inputText = inputText; notifyPropertyChanged(BR.inputText); } }
activity_main:
<layout xmlns:android="http://schemas.android.com/apk/res/android"> <data> <variable name="viewModel" type="com.example.ViewModel" /> </data> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@={viewModel.inputText}" /> <!-- 其他视图 --> </LinearLayout> </layout>
例四、使用@bindingAdapter注解加载图片
@BindingAdapter
注解是用于在 DataBinding 中绑定自定义属性和方法的注解。通过 @BindingAdapter
注解,我们可以定义一个静态方法,在该方法中实现各种自定义的数据绑定逻辑。
MainActivity :
package com.example.databinding32; import androidx.appcompat.app.AppCompatActivity; import androidx.databinding.DataBindingUtil; import android.os.Bundle; import com.example.databinding32.databinding.ActivityMainBinding; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ActivityMainBinding mainBinding =DataBindingUtil.setContentView(this,R.layout.activity_main); mainBinding.setNetworkImage("https://img-home.yssmx.com/images/20201124032511.png"); // mainBinding.setLocalImage(R.drawable.ic_launcher_background); } }
ImageBindingAdapter :
package com.example.databinding32; import android.text.TextUtils; import android.widget.ImageView; import androidx.databinding.BindingAdapter; import com.squareup.picasso.Picasso; public class ImageBindingAdapter { // 加载网络图片 @BindingAdapter("image") public static void setImage(ImageView image,String url){ if (!TextUtils.isEmpty(url)){ Picasso.get() .load(url) .placeholder(R.drawable.ic_launcher_background) .into(image); }else { image.setImageResource(R.drawable.ic_launcher_background); } } // 加载本地图片 @BindingAdapter("image") public static void setImage(ImageView image,int resId){ image.setBackgroundResource(resId); } // 如果没有url就加载本地图片 @BindingAdapter(value = {"image","defaultImageResources"},requireAll = false) public static void setImage(ImageView image,String url,int resId){ if (!TextUtils.isEmpty(url)){ Picasso.get() .load(url) .placeholder(R.drawable.ic_launcher_background) .into(image); }else { image.setBackgroundResource(resId); } } }
activity_main:
<?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="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" android:layout_width="250dp" android:layout_height="250dp" app:image="@{networkImage}" app:defaultImageResources="@{localImage}" 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>
注意事项:
使用 @BindingAdapter
注解时,需要注意以下几点:
注解位置:
@BindingAdapter
注解可以应用于任何静态方法上。方法参数:
@BindingAdapter
方法通常具有两个参数:视图对象(例如TextView
、ImageView
)和要绑定的属性值(例如字符串、图像资源等)。方法可以有任意多个参数,但前两个参数必须是视图对象和对应的属性值。方法命名:为了与属性关联,方法名称通常以
"set"
开头,后面跟着要绑定的属性的名称。例如,如果要绑定imageUrl
属性,方法可以被命名为setImageUrl(ImageView view, String url)
。参数注解:当
@BindingAdapter
方法有多个参数时,可以使用其他注解来标识不同的参数。例如,可以使用@BindingAdapter({"imageUrl", "placeholder"})
来指定方法的第一个参数对应的是imageUrl
属性,第二个参数对应的是placeholder
属性。属性名称:在布局文件中,可以使用
app:属性名称
的方式来设置自定义的绑定属性。例如,app:imageUrl="@{viewModel.imageUrl}"
。
三、总结
使用 DataBinding 的主要意义在于简化安卓应用中的数据绑定和 UI 更新过程,提高开发效率和代码可读性。以下是使用 DataBinding 的一些重要意义:
1. 简化代码结构:通过 DataBinding,可以将布局文件和数据源直接绑定,从而减少了编写繁琐的 findViewById() 和手动设置数据的代码。这样可以使代码更加简洁、清晰,并且减少了因为手动更新 UI 导致的错误。
2. 减少空指针异常:DataBinding 使用空安全的表达式语言,可以避免由于数据为空而导致的空指针异常。通过在表达式中处理 null 值,可以确保安全地访问和操作数据。
3. 提高性能:Data Binding 可以实现数据与界面的实时绑定,只有当数据发生变化时才会触发 UI 的更新,相比传统的手动更新方式,能够有效地降低不必要的 UI 刷新,提高应用的性能和响应速度。
4. 支持双向绑定:DataBinding 支持双向绑定,即可以将用户对 UI 的修改反映到数据源中。这样可以轻松地实现表单输入、状态切换等功能,无需额外的回调或监听器。
5. 增强代码可读性:使用 DataBinding,可以将 UI 相关的代码和业务逻辑分离,使代码结构更加清晰,提高了代码的可读性和维护性。开发者可以专注于处理数据和逻辑层面,而不需要直接操作界面元素。
总之,使用 DataBinding 可以简化数据绑定过程、提高性能和代码可读性,减少错误,并提供了更灵活的数据绑定和双向绑定功能。它是一种强大的工具,可以提升安卓应用的开发效率和用户体验。文章来源:https://www.toymoban.com/news/detail-575490.html
未完待续。。。。。。文章来源地址https://www.toymoban.com/news/detail-575490.html
到了这里,关于DataBinding在Android应用中的深入解析与实战的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!