Android Jetpack ViewModel 的使用

官网镇楼 ViewModel 概览 | Android 开发者 | Android Developers
https://developer.android.google.cn/topic/libraries/architecture/viewmodel?hl=zh_cn#kotlin

ViewModel 类旨在以注重生命周期的方式存储和管理界面相关的数据。

ViewModel 类让数据可在发生屏幕旋转等配置更改后继续留存。

ViewModel 是用于管理数据的,界面上的数据,都应该放到 ViewModel 中,简化 Activity 和 Fragment 中的逻辑。

开始使用。

1.添加依赖

dependencies {

    // ViewModel
    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0"
}

2.创建 ViewModel

创建 MyViewModel ,继承 ViewModel 。

所有与页面相关的数据都放在 ViewModel 中。

本例简单,就放一个数据。

import androidx.lifecycle.ViewModel

class MyViewModel : ViewModel() {

    /**
     * 所有与页面相关的数据都放在 ViewModel 中
     * */

    var num = 0
}

3.实例化 ViewModel 和使用

class ViewModelActivity : AppCompatActivity() {

    lateinit var myViewModel: MyViewModel

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

        sp = getPreferences(Context.MODE_PRIVATE)
        myViewModel = ViewModelProvider(this).get(MyViewModel::class.java)

        button1.setOnClickListener {
            myViewModel.num++
            refreshText()
        }

        refreshText()
    }

    fun refreshText(){
        textview.text = myViewModel.num.toString()
    }
}

lateinit 是 Kotlin 的关键字,用于延迟初始化。

如例子中的 ViewModelProvider(this).get(MyViewModel::class.java)

实例化 ViewModel 的格式是: ViewModelProvider(<要用ViewModel的Activity或者Fragment的实例>).get(<创建的ViewModel>::class.java)

补充布局,很简单,就一个 TextView 、一个 Button,

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:id="@+id/textview"
        android:gravity="center"
        android:textSize="30sp"
        android:textColor="@color/design_default_color_secondary"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

    <Button
        android:id="@+id/button1"
        android:text="Button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
</LinearLayout>

这就是 ViewModel 的基本使用了。

4.给ViewModel传递数据

上面是例子是从 ViewModel 读取数据,怎么给ViewModel传递数据呢?

ViewModelProvider.Factory

4.1 创建 ViewModelProvider.Factory

创建 MyViewModelFactory ,继承 ViewModelProvider.Factory ,重写 create() 方法。

import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider

class MyViewModelFactory(private val data:Int) : ViewModelProvider.Factory {

    override fun <T : ViewModel?> create(modelClass: Class<T>): T {
        //TODO("Not yet implemented")
        return MyViewModel(data) as T
    }
}

4.2 修改 ViewModel ,构造函数中是要传递的数据

import androidx.lifecycle.ViewModel

class MyViewModel(data : Int) : ViewModel() {

    /**
     * 所有与页面相关的数据都放在 ViewModel 中
     * */

    var num = data
}

4.3 使用 ViewModelProvider.Factory 实例化 ViewModel

class ViewModelActivity : AppCompatActivity() {

    lateinit var myViewModel: MyViewModel
    lateinit var sp: SharedPreferences

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

        sp = getPreferences(Context.MODE_PRIVATE)
        val last = sp.getInt("key_last_data", 0)
        
        //myViewModel = ViewModelProvider(this).get(MyViewModel::class.java)        
        myViewModel = ViewModelProvider(this, MyViewModelFactory(last)).get(MyViewModel::class.java)

        button1.setOnClickListener {
            myViewModel.num++
            refreshText()
        }

        refreshText()
    }

    fun refreshText(){
        textview.text = myViewModel.num.toString()
    }

    override fun onPause() {
        super.onPause()
        sp.edit {
            putInt("key_last_data", myViewModel.num)
        }
    }
}

原来的实例化方法是: myViewModel = ViewModelProvider(this).get(MyViewModel::class.java) ,
对应 ViewModelProvider(@NonNull ViewModelStoreOwner owner)

使用 ViewModelProvider.Factory 后,实例化方法是 :
myViewModel = ViewModelProvider(this, MyViewModelFactory(last)).get(MyViewModel::class.java) ,
对应 ViewModelProvider(@NonNull ViewModelStoreOwner owner, @NonNull Factory factory)

Android Jetpack ViewModel 的使用

然后使用 SharedPreferences 保存数据。

上一篇:15个经典面试问题,阿里巴巴内部Jetpack宝典意外流出


下一篇:【原创】Jetpack Compose学习笔记(一)