• Android(kotlin)JetPack系列学习——2.ViewModel(含源码)


    1. 简介

    (1)ViewModel 类旨在以注重生命周期的方式存储和管理界面相关数据。ViewModel 类让数据可在发生屏幕旋转等配置更改后继续留存
    (2)对于简单的数据,activity 可以使用 onSaveInstanceState() 方法从 onCreate() 中的捆绑包恢复其数据,但此方法仅适合可以序列化再反序列化的少量数据,而不适合数量可能较大的数据,如用户列表或位图。这种情况就可以使用ViewModel来解决!
    (3)根据之前在公司实习的经验,数据相关的都放在ViewModel中,一般就没大问题!

    2. 使用

    Step1: 引入依赖

    plugins {
        id 'com.android.application'
        id 'org.jetbrains.kotlin.android'
        id 'kotlin-kapt'
    }
    
    android {
        compileSdk 32
    
        defaultConfig {
            applicationId "com.exam.viewmodel"
            minSdk 21
            targetSdk 32
            versionCode 1
            versionName "1.0"
    
            testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        }
    
        buildTypes {
            release {
                minifyEnabled false
                proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
            }
        }
        compileOptions {
            sourceCompatibility JavaVersion.VERSION_1_8
            targetCompatibility JavaVersion.VERSION_1_8
        }
        kotlinOptions {
            jvmTarget = '1.8'
        }
    
        buildFeatures{
            viewBinding = true
            dataBinding = true
        }
    }
    
    dependencies {
    
        implementation 'androidx.core:core-ktx:1.7.0'
        implementation 'androidx.appcompat:appcompat:1.3.0'
        implementation 'com.google.android.material:material:1.4.0'
        implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
        testImplementation 'junit:junit:4.13.2'
        androidTestImplementation 'androidx.test.ext:junit:1.1.3'
        androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
    
        // 监听整个应用程序的生命周期
        implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.3.1'
        implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1'
        implementation 'androidx.lifecycle:lifecycle-process:2.5.1'
        // viewModel的获取
        implementation 'androidx.fragment:fragment-ktx:1.5.2'
        // room
        implementation "androidx.room:room-runtime:2.4.3"
        kapt "androidx.room:room-compiler:2.4.3"
        // navigation
        implementation "androidx.navigation:navigation-fragment-ktx:2.5.2"
        implementation "androidx.navigation:navigation-ui-ktx:2.5.2"
        // paging
        implementation "androidx.paging:paging-runtime:3.1.1"
        // retrofit
        implementation "com.squareup.retrofit2:retrofit:2.9.0"
        implementation "com.squareup.retrofit2:converter-gson:2.9.0"
        // hilt注入
        implementation "com.google.dagger:hilt-android:2.28-alpha"
        kapt "com.google.dagger:hilt-android-compiler:2.28-alpha"
        // 使viewModel在Activity中可以向之前一样实例化
        implementation 'androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha02'
        kapt 'androidx.hilt:hilt-compiler:1.0.0-alpha02'
        // 协程
        implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.1.1"
        implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.1.1"
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77

    2.1 在Activity中使用

    Step1: 建立ViewModel类

    class MainActivityViewModel: ViewModel() {
        private var i = 0
        private val testNum = MutableLiveData<Int>()
    
        fun getTestNum(): MutableLiveData<Int>{
            return testNum
        }
    
        fun addOne(){
            i++
            testNum.value = i
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    Step2: 在activity中实例化它,并使用

    class MainActivity : AppCompatActivity() {
    
        private val viewModel: MainActivityViewModel by viewModels()
        private lateinit var binding: ActivityMainBinding
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            binding = ActivityMainBinding.inflate(layoutInflater)
            setContentView(binding.root)
    
            // 使用viewmodel
            viewModel.getTestNum().observe(this){
                binding.tvText.text = it.toString()
            }
    
            click()
        }
    
        private fun click(){
            binding.btnAdd.setOnClickListener {
                viewModel.addOne()
            }
    
            binding.btnGoToSecondActivity.setOnClickListener {
                val intent: Intent = Intent(this, SecondActivity::class.java)
                startActivity(intent)
            }
        }
        
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    这样在数据ViewModel中的数据使用LiveData,在Activity中不对数据进行处理,这样即使屏幕翻转,数据也不会消失。

    2.2 fragment共享数据

    有了ViewModel后, fragment之间的数据共享变得简单了起来。思路非常简单:
    Step1: 新建公共的ViewModel类

    class FragmentViewModel: ViewModel() {
        private val testLiveData = MutableLiveData<Int>()
        private var i = 0
    
        fun getLiveData(): MutableLiveData<Int> {
            return testLiveData
        }
    
        fun addOne(){
            i++
            testLiveData.value = i
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    Step2: 在两个fragment中分别实例化同一个ViewModel即可
    LeftFragment:

    class LeftFragment : Fragment() {
    
        private val viewModel: FragmentViewModel by activityViewModels()
        private lateinit var binding: FragmentLeftBinding
    
        override fun onCreateView(
            inflater: LayoutInflater,
            container: ViewGroup?,
            savedInstanceState: Bundle?
        ): View? {
            binding = FragmentLeftBinding.inflate(layoutInflater, container, false)
            return binding.root
        }
    
        override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
            super.onViewCreated(view, savedInstanceState)
    
            activity?.let { viewModel.getLiveData().observe(it){
                    binding.tvLeft.text = it.toString()
                }
            }
    
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    RightFragment:

    class RightFragment : Fragment() {
        private val viewModel: FragmentViewModel by activityViewModels()
        private lateinit var binding: FragmentRightBinding
    
        override fun onCreateView(
            inflater: LayoutInflater,
            container: ViewGroup?,
            savedInstanceState: Bundle?
        ): View? {
            binding = FragmentRightBinding.inflate(layoutInflater, container, false)
            return binding.root
        }
    
        override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
            super.onViewCreated(view, savedInstanceState)
            activity?.let { viewModel.getLiveData().observe(it){
                    binding.tvRight.text = it.toString()
                }
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    这样就能非常高效的使得数据共享。

    以下全部代码如下:
    JetPackStudyDemo全部代码,欢迎star

  • 相关阅读:
    互关互关互关
    使用python-pptx修改幻灯片背景:设置或更改幻灯片的背景颜色和图片
    jsp的四大作用域
    Simplicity Studio 生成的工程移植到 Linux 上编译
    c++ SqliteCPP 使用-根据列名获取数据类型(3)
    [七夕节]——一款基于canvas绘制五颜六色线条合成一个爱心发光动画特效
    C/C++超市收银系统
    git常用命令和开发常用场景
    ChatGPT暂时停止开通plus,可能迎来封号高峰期
    瀑布流布局
  • 原文地址:https://blog.csdn.net/qq_41915623/article/details/127658602