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

安卓开发之LiveData与DataBinding

LiveData——生命周期感知

LiveData 是 Android Jetpack 提供的一个生命周期感知的数据持有者类,它可以用于持有数据并在数据发生变化时通知观察者。LiveData 常与 ViewModel 配合使用,帮助简化 UI 层和数据层之间的交互,确保 UI 在合适的生命周期内接收数据更新。

它是一种数据持有者,它遵循观察者模式。当数据变化时,LiveData 会通知所有的观察者进行更新。不同于普通的可变数据,LiveData 具有生命周期感知的特性,能够自动管理视图组件(如 Activity 或 Fragment)的生命周期。

核心特性:

  • 生命周期感知:LiveData 仅在处于活动状态(如前台)的生命周期所有者中触发更新,避免了内存泄漏。
  • 自动管理 UI 更新:UI 会自动响应数据变化,不需要手动刷新视图。
  • 线程安全:LiveData 默认是线程安全的,可以跨线程更新数据。

LiveData 的工作原理

LiveData 的核心工作原理是通过与生命周期感知的组件(如 Activity 或 Fragment)进行绑定。当 LiveData 的数据发生变化时,它会通知所有处于活跃状态的观察者,并更新 UI。

生命周期关联的内部工作原理

LiveData 通过观察 Lifecycle 状态实现与生命周期的关联:

  1. 注册观察者时:当调用 observe 方法时,LiveData 会检查 LifecycleOwner 的当前状态。
  • 如果 LifecycleOwner 是活跃状态(STARTED 或 RESUMED),立即通知观察者当前值。
  • 如果是非活跃状态,等待其变为活跃状态后再通知。
  1. 生命周期变化时:
  • 当 LifecycleOwner 转变为活跃状态时,LiveData 开始发送数据更新。
  • 当 LifecycleOwner 转变为非活跃状态时,LiveData 停止通知。

LiveData 的基本使用

添加 LiveData 依赖

LiveData 是 Android Jetpack 库的一部分,需要在 build.gradle 文件中添加相关的依赖。

在 app/build.gradle 中添加依赖:

dependencies { //如果是kotlin项目 implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.6.1" implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1" // ViewModel 依赖 //java项目 implementation "androidx.lifecycle:lifecycle-livedata:2.6.1" // Java 支持的 LiveData 版本 implementation "androidx.lifecycle:lifecycle-viewmodel:2.6.1" // Java 支持的 ViewModel 版本 }

创建 LiveData

LiveData 可以通过 LiveData 类或 MutableLiveData 类进行创建。LiveData 是不可变的,而 MutableLiveData 是可变的,通常通过 MutableLiveData 来更新数据。

// 创建一个 LiveData LiveData<String> userData = new MutableLiveData<>();

设置数据

使用 setValue() 或 postValue() 来设置 LiveData 的数据。

  • setValue():仅在主线程中调用。
  • postValue():可以在任何线程中调用,最终会在主线程更新 UI。

MutableLiveData<String> liveData = new MutableLiveData<>(); liveData.setValue("Hello, LiveData!"); // 在主线程中更新数据

liveData.postValue("Updated from background thread!"); // 在后台线程中更新数据

观察 LiveData

通过 observe() 方法来观察 LiveData 的变化。observe() 方法需要传入一个生命周期所有者(如 Activity 或 Fragment)和一个 Observer。

//这里的this 指的就是生命周期所有者,LiveData会检查当前的生命周期变化,只有在活跃状态下才会通知 liveData.observe(this, new Observer<String>() { @Override public void onChanged(String data) { // 数据变化时更新 UI textView.setText(data); } });

在上面的例子中,observe() 方法会在 LiveData 的数据发生变化时触发 onChanged() 回调,并更新 TextView。

LiveData 的应用场景

结合 ViewModel 使用

LiveData 经常与 ViewModel 一起使用,在 ViewModel 中持有数据,并通过 LiveData 向 UI 层提供数据。

public class UserViewModel extends ViewModel { private MutableLiveData<User> userLiveData = new MutableLiveData<>(); public LiveData<User> getUser() { return userLiveData; } public void loadUserData() { // 模拟从网络加载数据 userLiveData.setValue(new User("John Doe", "john@example.com")); } }

在 Activity 或 Fragment 中观察 LiveData:

public class UserActivity extends AppCompatActivity { private UserViewModel viewModel; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_user); viewModel = new ViewModelProvider(this).get(UserViewModel.class); viewModel.getUser().observe(this, new Observer<User>() { @Override public void onChanged(User user) { // 更新 UI usernameTextView.setText(user.getName()); } }); // 加载用户数据 viewModel.loadUserData(); } }

网络请求与 LiveData

LiveData 可以与网络请求结合使用,在网络请求完成时更新 UI。

public class UserViewModel extends ViewModel { private MutableLiveData<User> userLiveData = new MutableLiveData<>(); private UserRepository userRepository = new UserRepository(); public LiveData<User> getUser() { return userLiveData; } public void loadUserData() { //发起一个网络请求后,处理结果成功或者失败 userRepository.getUserData(new Callback<User>() { @Override public void onSuccess(User user) { userLiveData.setValue(user); // 成功时更新 LiveData } @Override public void onFailure(Throwable t) { userLiveData.setValue(null); // 失败时更新 LiveData } }); } }

LiveData 的高级功能(可自行扩展)

MediatorLiveData

MediatorLiveData 是 LiveData 的子类,它允许合并多个 LiveData 对象的数据并根据多个 LiveData 的变化来更新 UI。

MediatorLiveData<String> mediatorLiveData = new MediatorLiveData<>(); LiveData<String> liveData1 = new MutableLiveData<>(); LiveData<String> liveData2 = new MutableLiveData<>(); mediatorLiveData.addSource(liveData1, new Observer<String>() { @Override public void onChanged(String s) { mediatorLiveData.setValue(s); } }); mediatorLiveData.addSource(liveData2, new Observer<String>() { @Override public void onChanged(String s) { mediatorLiveData.setValue(s); } });

Transformations

Transformations 允许对 LiveData 进行转换操作,如映射、切换等。常见的转换包括 map() 和 switchMap()。

LiveData<String> transformedLiveData = Transformations.map(liveData, new Function<String, String>() { @Override public String apply(String input) { return input.toUpperCase(); // 将字符串转换为大写 } });

LiveData 的优点

  • 生命周期感知:自动管理数据的观察者,避免了内存泄漏。
  • UI 更新简化:无需手动更新 UI,数据更新后会自动通知 UI 层。
  • 线程安全:可以跨线程更新 LiveData。
  • 与 ViewModel 完美结合:提高了数据管理的清晰度和可维护性。

LiveData 的缺点

  • 单一线程更新:setValue() 仅支持主线程更新,若在非主线程更新需使用 postValue()。
  • 不可取消的观察:LiveData 一旦与生命周期绑定,不能手动取消观察,必须依赖生命周期的自动管理。

总结

LiveData 是 Android 中非常有用的数据持有者类,尤其适合与 ViewModel 配合使用。它通过生命周期感知机制和观察者模式,使得 UI 更新更加简洁且高效,避免了内存泄漏和无效的 UI 更新。掌握 LiveData 的使用,对于构建现代化的 Android 应用是非常重要的。

Databinding——数据绑定

DataBinding 是 Android Jectpack提供的一种用于简化 UI 组件与数据之间绑定的技术。它使得 UI 更新更加简洁,减少了大量的冗余代码(如 findViewById 和手动设置 UI 的操作),并且提升了开发效率。在 MVVM 架构中,DataBinding 主要用来简化 ViewModel 和 View 之间的交互。

核心概念:

  • Binding Layout:使用 DataBinding 时,布局文件通常会变为一个 binding 布局文件,它包含了 标签和数据绑定的表达式。
  • Binding Object:通过 DataBinding 在布局文件中生成一个绑定对象,这个对象可以直接与 ViewModel 或其他数据对象交互。
  • Binding Expressions:在布局文件中使用表达式来绑定数据,如绑定 TextView 的文本、按钮的点击事件等。

开启 DataBinding

要使用 DataBinding,首先需要在项目中启用 DataBinding。在 build.gradle 文件中进行设置:

android { dataBinding { enabled = true } }

DataBinding 的工作流程

  1. XML 布局文件:在布局文件中使用 标签来包装 UI 组件,并且声明变量。
  2. ViewModel / Model:在 Activity 或 Fragment 中,通过 ViewModel 提供数据或操作。
  3. Binding Object:在 Activity/Fragment 中通过 DataBinding 绑定 UI 和数据,自动更新视图。

DataBinding 的基本使用

步骤 1:创建布局文件

DataBinding 布局文件需要以 标签包裹,定义视图与 ViewModel 的绑定关系。

布局文件(activity_main.xml):

<layout xmlns:android="http://schemas.android.com/apk/res/android"> <data> <!-- 声明绑定的 ViewModel --> <variable name="viewModel" type="com.example.app.UserViewModel" /> </data> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:id="@+id/tvUsername" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{viewModel.username}" /> <Button android:id="@+id/btnLogin" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Login" android:onClick="@{() -> viewModel.onLoginClicked()}" /> </LinearLayout> </layout>

  • 标签用于声明数据绑定变量。
  • @{} 语法用于绑定数据和视图属性。
  • android:text="@{viewModel.username}" 表示将 viewModel 中的 username 绑定到 TextView 上。

步骤 2:创建 ViewModel

ViewModel 存放业务逻辑和 UI 数据。

public class UserViewModel extends ViewModel { private MutableLiveData<String> username = new MutableLiveData<>(); public LiveData<String> getUsername() { return username; } public void onLoginClicked() { username.setValue("Hello, User!"); } }

  • 使用 LiveData 来提供数据绑定,username 是一个 LiveData 对象,Activity 会观察其变化并自动更新 UI。

步骤 3:在 Activity 中绑定 ViewModel

在 Activity 中,绑定布局文件和 ViewModel。

public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main); // 创建 ViewModel UserViewModel viewModel = new ViewModelProvider(this).get(UserViewModel.class); // 绑定 ViewModel 到布局 binding.setViewModel(viewModel); binding.setLifecycleOwner(this); } }

  • DataBindingUtil.setContentView() 方法用于绑定布局。
  • binding.setViewModel() 方法将 ViewModel 传递给布局。

DataBinding 高级功能

双向数据绑定

在某些场景下,我们需要从 UI 获取输入数据并将其反馈给 ViewModel。DataBinding 支持双向绑定,即在 UI 和 ViewModel 之间建立双向数据流。

<EditText android:id="@+id/etUsername" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@={viewModel.username}" />

这里 @={} 表示双向绑定。编辑框中的内容会自动与 ViewModel 中的 username 进行绑定,UI 更新时 ViewModel 更新,ViewModel 更新时 UI 也会自动更新。

自定义绑定适配器

如果某些视图组件的属性不能直接绑定,可以通过自定义 BindingAdapter 来实现。

自定义 BindingAdapter:

@BindingAdapter("app:imageUrl") public static void setImageUrl(ImageView view, String url) { Glide.with(view.getContext()) .load(url) .into(view); }

布局文件使用:

<ImageView android:id="@+id/imgProfile" android:layout_width="wrap_content" android:layout_height="wrap_content" app:imageUrl="@{viewModel.profileImageUrl}" />

这里 app:imageUrl 会调用自定义的 setImageUrl() 方法来设置图片。

事件处理

DataBinding 支持事件绑定(如按钮点击事件)。

XML 布局:

<Button android:id="@+id/btnLogin" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="@{() -> viewModel.onLoginClicked()}" android:text="Login" />

ViewModel 方法:

public void onLoginClicked() { // 处理登录点击事件 }

DataBinding 的优点

  • 减少冗余代码:DataBinding 大大减少了手动查找视图 (findViewById) 和更新视图的代码。
  • 提升开发效率:通过在 XML 文件中进行绑定,简化了逻辑并降低了 UI 更新的复杂度。
  • 更好的解耦:DataBinding 实现了 View 和 ViewModel 的解耦,View 只关心数据的显示,不直接处理数据逻辑。

DataBinding 的缺点

  • 学习曲线:DataBinding 对于初学者可能有些复杂,理解和配置时需要一定的时间。
  • 性能开销:由于 DataBinding 会生成大量的绑定类,可能会导致编译时间稍长,但通常这个开销是可以接受的。

总结

DataBinding 是 Android 中一种非常强大且常用的技术,特别是在 MVVM 架构中,可以显著提高 UI 更新的效率和简洁度。通过使用 DataBinding,我们可以更容易地管理视图与数据之间的绑定,减少手动更新视图的代码,并实现双向数据绑定和事件处理。虽然学习复杂,但对于大型应用和复杂的数据绑定场景来说,DataBinding 的优势是显而易见的。

http://www.dtcms.com/a/99661.html

相关文章:

  • Next.js 项目生产构建优化
  • 【leetcode hot 100 45】跳跃游戏Ⅱ
  • 第三百八十九节 JavaFX教程 - JavaFX WebEngine
  • uniapp-小程序地图展示
  • C++的模板(十四):更多的自动内存管理
  • AI的未来在手机里!
  • Spring Data审计利器:@LastModifiedDate详解(依赖关系补充篇)!!!
  • springBoot与ElementUI配合上传文件
  • Vue2——常用指令总结、指令修饰符、v-model原理、computed计算属性、watch监听器、ref和$refs
  • Elasticsearch(ES)的经典面试题及其答案
  • 深度对比:DeepSeek vs OpenAI 核心技术指标
  • Matlab安装tdms插件
  • Numpy用法(三)
  • QT操作Excel
  • 【 <二> 丹方改良:Spring 时代的 JavaWeb】之 Spring Boot 中的缓存技术:使用 Redis 提升性能
  • NodeJs之http模块
  • 学成在线--day02
  • 深度学习篇---模型训练评估参数
  • Tabby二:使用笔记 - 保姆级教程
  • C#的CSV 在8859-1下中乱码和技巧
  • 猜猜我用的是哪个大模型?我的世界游戏界面简单的模拟效果
  • 网络华为HCIA+HCIP 策略路由,双点双向
  • OSPF练习
  • Let’s Encrypt 宣布推出短期证书与 IP 地址支持,推动 Web 安全迈向新高度
  • 无线通信技术(二):ITU、3GPP及传统波段对无线频谱的划分
  • AutoDev 2.0 正式发布:智能体 x 开源生态,AI 自动开发新标杆
  • 计算机组成原理笔记(六)——2.2机器数的定点表示和浮点表示
  • React Router精通:轻松创建动态单页应用
  • 动态IP:网络世界的“变色龙”如何改变你的在线体验?
  • 革新汽车安全通信技术,美格智能全系车载通信模组支持NG-eCall