前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >你真的了解ViewModel的设计思想吗?

你真的了解ViewModel的设计思想吗?

作者头像
Rouse
发布2024-01-23 15:52:08
1400
发布2024-01-23 15:52:08
举报
文章被收录于专栏:Android补给站Android补给站

引言

Android开发中,数据的管理是一个至关重要的问题。随着应用复杂度的增加,我们需要一种能够有效管理数据和处理UI相关逻辑的机制。Android架构组件中的ViewModel应运而生。本文将深入探讨ViewModel的原理,并介绍其高级运用,旨在帮助开发者更好地理解和运用这一组件。

什么是ViewModel?

ViewModel是一种设计模式,它的目标是将UI控制器(Activity、Fragment等)与数据分离,同时保持UI的状态。在Android中,ViewModel通常用于存储和管理与UI相关的数据,以确保这些数据在屏幕旋转或配置更改等情况下不会丢失。

原理解析

ViewModel的原理是基于ViewModelStore类。ViewModelStore类是一个存储ViewModel的容器。当UI控制器创建时,系统会为其创建一个ViewModelStore实例。当 UI控制器销毁时,系统会销毁其对应的ViewModelStore实例。

ViewModel在创建时,会将自身注册到其所在的ViewModelStore实例中。当UI控制器销毁时,系统会从其对应的ViewModelStore实例中移除ViewModel

代码语言:javascript
复制

open class ViewModelStore {

    //存储viewmodel
    private val map = mutableMapOf<String, ViewModel>()
    ...

}

// 自动创建
getLifecycle().addObserver(new LifecycleEventObserver() {
    @Override
    public void onStateChanged(@NonNull LifecycleOwner source,
            @NonNull Lifecycle.Event event) {
        ensureViewModelStore();
        getLifecycle().removeObserver(this);
    }
});

// 销毁
getLifecycle().addObserver(new LifecycleEventObserver() {
    @Override
    public void onStateChanged(@NonNull LifecycleOwner source,
            @NonNull Lifecycle.Event event) {
        if (event == Lifecycle.Event.ON_DESTROY) {
            // Clear out the available context
            mContextAwareHelper.clearAvailableContext();
            // And clear the ViewModelStore
            if (!isChangingConfigurations()) {
                getViewModelStore().clear();
            }
            mReportFullyDrawnExecutor.activityDestroyed();
        }
    }
});

所以ViewModelStore的创建与ViewModel的销毁,都与Lifecycle有关,这样就让ViewModel具有以下特性:

  1. 生命周期感知: ViewModel是生命周期感知的,它会自动跟踪UI控制器的生命周期,并在适当的时候进行清理。这意味着我们无需担心内存泄漏或不必要的资源占用。
  2. 持久性存储: ViewModel可以存储大量的数据,并且在配置更改时仍然保持活动。这是通过将ViewModel与UI控制器分离,将其保存在ViewModelStore中实现的。
  3. 数据共享: 多个UI控制器可以共享同一个ViewModel,这为不同组件之间的数据共享提供了便利。这对于在Activity和Fragment之间传递数据非常有用。

为什么需要ViewModelStore

ViewModelStore是用于管理ViewModel实例的生命周期的一种机制。它的存在是为了解决以下问题:

  1. 生命周期一致性:在Android开发中,我们经常遇到配置更改(如屏幕旋转)导致Activity或Fragment被销毁并重新创建的情况。这种情况下,我们希望保持与UI相关的数据的一致性,即使UI重新创建,数据也不会丢失。ViewModelStore通过管理ViewModel实例的生命周期,确保在重新创建UI时,旧的ViewModel实例被正确地销毁,而新的ViewModel实例被正确地创建。
  2. 资源管理:每个ViewModel实例可能持有一些资源,如数据库连接、网络连接等。如果这些资源没有被正确地释放,就会导致内存泄漏和资源浪费。ViewModelStore通过在适当的时机销毁ViewModel实例,确保这些资源可以被正确地释放,避免了内存泄漏和资源浪费。
  3. 数据共享:ViewModelStore允许多个组件共享同一个ViewModel实例。这在某些情况下非常有用,比如一个Activity和它的多个Fragment需要访问和更新相同的数据。通过使用ViewModelStore,这些组件可以共享同一个ViewModel实例,避免了数据的重复加载和同步问题。

简单示例

以下是一个简单的ViewModel示例,演示了如何使用ViewModel来保存和管理数据:

代码语言:javascript
复制
class MyViewModel : ViewModel() {
    private val state = MutableLiveData<String>()

    fun setData(value: String) {
        sate.value = value
    }

    fun getData(): LiveData<String> {
        return state
    }
}

class MyActivity : AppCompatActivity() {

    private val viewModel: MyViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // 观察 ViewModel 的数据变化
        viewModel.getData().observe(this, { data ->
            // 更新 UI
        })
    }
}

在上述代码中,ViewModel包含一个MutableLiveData来存储数据。通过setData和getData方法,我们可以设置和获取数据。这个ViewModel将在配置更改时保持活动,确保数据不会丢失。

高级运用

使用SavedStateHandle

SavedStateHandle是一个可用于在配置更改后保持数据的工具。它允许我们将数据与ViewModel关联,以便在应用重新创建时检索。

代码语言:javascript
复制
class MyViewModel(private val savedStateHandle: SavedStateHandle) : ViewModel() {
    private val dataKey = "data_key"

    fun setData(value: String) {
        savedStateHandle.set(dataKey, value)
    }

    fun getData(): String? {
        return savedStateHandle.get(dataKey)
    }
}

处理异步操作

ViewModel可以与协程结合,以处理异步操作。这使得在ViewModel中执行耗时操作成为可能,而不会阻塞UI线程。

代码语言:javascript
复制
class MyViewModel : ViewModel() {
    private val data = MutableLiveData<String>()

    fun fetchData() {
        viewModelScope.launch {
            // 执行耗时操作
            val result = fetchDataFromRepository()
            data.value = result
        }
    }

    fun getData(): LiveData<String> {
        return data
    }
}

使用Factory

ViewModelProvider.Factory用于自定义ViewModel的创建过程,可以传递参数ViewModel的构造函数。

代码语言:javascript
复制
class MyViewModelFactory(private val repository: MyRepository) : ViewModelProvider.Factory {

    override fun <T : ViewModel?> create(modelClass: Class<T>): T {
        if (modelClass.isAssignableFrom(MyViewModel::class.java)) {
            return MyViewModel(repository) as T
        }
        throw IllegalArgumentException("Unknown ViewModel class")
    }
}

注意事项和优化技巧

  • 避免在ViewModel中持有View的引用,以防止内存泄漏。
  • ViewModel的职责限制在处理UI相关的逻辑,不要包含过多的业务逻辑。
  • 谨慎使用SavedStateHandle,避免将大量数据存储在其中导致性能问题。

结语

通过深入理解ViewModel的原理和高级运用,我们可以更好地利用这一强大的架构组件。ViewModel的设计模式和生命周期感知使其成为Android开发中不可或缺的一部分。希望本文能够帮助大家更好地应用和理解ViewModel

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2024-01-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Android补给站 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 引言
  • 什么是ViewModel?
  • 原理解析
  • 为什么需要ViewModelStore
  • 简单示例
  • 高级运用
    • 使用SavedStateHandle
      • 处理异步操作
        • 使用Factory
        • 注意事项和优化技巧
        • 结语
        相关产品与服务
        对象存储
        对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档