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

文章目录

    • 1. 简介
    • 2. 使用
      • 2.1 在Activity中使用
      • 2.2 fragment共享数据

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"

}

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
    }
}

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)
        }
    }
    
}

这样在数据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
    }
}

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()
            }
        }

    }

}

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()
            }
        }
    }
}

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

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

你可能感兴趣的:(安卓开发,android,kotlin,开发语言,jetpack,viewmodel)