盒子
盒子
文章目录
  1. 什么是ViewModel
  2. ViewModel的原理
    1. ViewModelStore和ViewModelStoreOwner
    2. ViewModelProvider
  3. 使用ViewModel
    1. 添加ViewModel依赖
    2. 创建ViewModel
    3. 在UI控制器中使用ViewModel
  4. ViewModel与跨组件通信
  5. ViewModel与SavedState
  6. ViewModel使用过程中的注意点
  7. 结论
  8. 推荐

深入理解与运用Android Jetpack ViewModel

在Android开发中,数据与界面的分离一直是一项重要的挑战。为了解决这个问题,Google推出了Android Jetpack组件之一的ViewModel。ViewModel是一种用于管理UI相关数据的架构组件,它能够帮助开发者实现优雅的数据驱动和生命周期管理。本文将深入浅出地介绍ViewModel的使用和原理,带你一步步掌握这个强大的组件。

什么是ViewModel

ViewModel是Android Jetpack组件之一,它的主要目的是将UI控制器(如Activity和Fragment)与数据相关的业务逻辑分开,使得UI控制器能够专注于展示数据和响应用户交互,而数据的获取和处理则交由ViewModel来管理。这种分离能够使代码更加清晰、易于测试和维护。

ViewModel的原理

ViewModel的原理其实并不复杂。在设备配置发生变化(如屏幕旋转)导致Activity或Fragment重建时,ViewModel不会被销毁,而是保留在内存中。这样,UI控制器可以在重建后重新获取之前的ViewModel实例,并继续使用其中的数据,从而避免数据丢失和重复加载。

ViewModelStore和ViewModelStoreOwner

ViewModel的原理涉及两个核心概念:ViewModelStore和ViewModelStoreOwner。

ViewModelStore是一个存储ViewModel实例的容器,它的生命周期与UI控制器的生命周期关联。在UI控制器(Activity或Fragment)被销毁时,ViewModelStore会清理其中的ViewModel实例,避免内存泄漏。

ViewModelStoreOwner是拥有ViewModelStore的对象,通常是Activity或Fragment。ViewModelProvider通过ViewModelStoreOwner来获取ViewModelStore,并通过ViewModelStore来管理ViewModel的生命周期。

ViewModelProvider

ViewModelProvider是用于创建和获取ViewModel实例的工具类。它负责将ViewModel与ViewModelStoreOwner关联,并确保ViewModel在合适的时机被销毁。

在Activity中获取ViewModel实例:

1
viewModel = new ViewModelProvider(this).get(MyViewModel.class);

在Fragment中获取ViewModel实例:

1
viewModel = new ViewModelProvider(this).get(MyViewModel.class);

使用ViewModel

添加ViewModel依赖

首先,确保你的项目已经使用了AndroidX,并在build.gradle中添加ViewModel依赖:

1
2
3
dependencies {
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1"
}

创建ViewModel

创建ViewModel非常简单,只需继承ViewModel类并在其中定义数据和相关操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class MyViewModel extends ViewModel {
private MutableLiveData<String> data = new MutableLiveData<>();

public LiveData<String> getData() {
return data;
}

public void fetchData() {
// 模拟异步数据获取
new Handler().postDelayed(() -> {
data.setValue("Hello, ViewModel!");
}, 2000);
}
}

在UI控制器中使用ViewModel

在Activity或Fragment中获取ViewModel的实例,并观察数据变化:

1
2
3
4
5
6
7
viewModel = new ViewModelProvider(this).get(MyViewModel.class);
viewModel.getData().observe(this, data -> {
// 更新UI
textView.setText(data);
});

viewModel.fetchData(); // 触发数据获取操作

ViewModel与跨组件通信

ViewModel不仅仅用于在单个UI控制器内部共享数据,它还可以用于在不同UI控制器之间共享数据,实现跨组件通信。例如,一个Fragment中的数据可以通过ViewModel传递给Activity。

在Activity中共享数据:

1
2
3
4
5
sharedViewModel = new ViewModelProvider(this).get(SharedViewModel.class);
sharedViewModel.getData().observe(this, data -> {
// 更新UI
textView.setText(data);
});

在Fragment中共享数据:

1
sharedViewModel = new ViewModelProvider(requireActivity()).get(SharedViewModel.class);

注意:在跨组件通信时,需要使用同一个ViewModelProvider获取相同类型的ViewModel实例。在Activity中,使用this作为ViewModelProvider的参数,在Fragment中,使用requireActivity()作为参数。

ViewModel与SavedState

有时,我们可能希望在ViewModel中保存一些与UI控制器生命周期无关的数据,以便在重建时恢复状态。ViewModel提供了SavedState功能,它可以让我们在ViewModel中持久化保存数据。

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class MyViewModel extends ViewModel {
private SavedStateHandle savedStateHandle;

public MyViewModel(SavedStateHandle savedStateHandle) {
this.savedStateHandle = savedStateHandle;
}

public LiveData<String> getData() {
return savedStateHandle.getLiveData("data");
}

public void setData(String data) {
savedStateHandle.set("data", data);
}
}

使用SavedStateViewModelFactory创建带有SavedState功能的ViewModel:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class MyActivity extends AppCompatActivity {
private MyViewModel viewModel;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

ViewModelProvider.Factory factory = new SavedStateViewModelFactory(getApplication(), this);
viewModel = new ViewModelProvider(this, factory).get(MyViewModel.class);

viewModel.getData().observe(this, data -> {
// 更新UI
textView.setText(data);
});

if (savedInstanceState == null) {
// 第一次创建时,触发数据获取操作
viewModel.fetchData();
}
}
}

ViewModel使用过程中的注意点

  • 不要在ViewModel中持有Context的引用,避免引发内存泄漏。
  • ViewModel应该只关注数据和业务逻辑,不应处理UI相关的操作。
  • 不要在ViewModel中保存大量数据,避免占用过多内存。
  • 当数据量较大或需要跨进程共享数据时,应该考虑使用其他解决方案,如Room数据库或SharedPreferences。

结论

通过本文的介绍,你已经了解了Android Jetpack ViewModel的使用与原理。ViewModel的出现极大地简化了Android开发中的数据管理和生命周期处理,使得应用更加健壮和高效。在实际开发中,合理使用ViewModel能够帮助你构建优雅、易维护的Android应用。

推荐

android_startup: 提供一种在应用启动时能够更加简单、高效的方式来初始化组件,优化启动速度。不仅支持Jetpack App Startup的全部功能,还提供额外的同步与异步等待、线程控制与多进程支持等功能。

AwesomeGithub: 基于Github的客户端,纯练习项目,支持组件化开发,支持账户密码与认证登陆。使用Kotlin语言进行开发,项目架构是基于JetPack\&DataBinding的MVVM;项目中使用了Arouter、Retrofit、Coroutine、Glide、Dagger与Hilt等流行开源技术。

flutter_github: 基于Flutter的跨平台版本Github客户端,与AwesomeGithub相对应。

android-api-analysis: 结合详细的Demo来全面解析Android相关的知识点, 帮助读者能够更快的掌握与理解所阐述的要点。

daily_algorithm: 每日一算法,由浅入深,欢迎加入一起共勉。

支持一下
赞赏是一门艺术