Android_Kotlin_Jetpack組件之ViewModel使用
- ViewModel概述
- ViewModel使用
- 1.依賴庫
- 2.創建ViewModel
- 3.向ViewModel傳遞引數
- 4. 簡單例子
??該文章作為學習總結與API查詢,如有錯誤歡迎各位大佬指正,對您有幫助的還望點贊支持下喲(* ^ ▽ ^ *)
??歡迎大家聊聊理解,互相探討,同時我也會將經典的問題更新到文章中,方便學習,
ViewModel概述
??ViewModel的作用,是專門用于存放與界面相關的資料的,幫助Activity分擔一部分作業,即,界面上能看到的資料,它的相關變數都應該存放在ViewModel中,而不是Activity中,以此來減少Activity中的邏輯,
- 當手機發生橫豎屏切換時,ViewModel不會被重新創建,這樣就可以保證界面上顯示的資料不會丟失,
- 推薦寫法:給每一個Activity和Fragment都創建一個對應的ViewModel
- ViewModel不能直接創建的原因,ViewModle有獨立的生命周期,其生命周期比Activity長,如果在Activity的生命周期 如:onCreate() 中,創建一個新的ViewModel,那么每次回呼都會進行創建,這樣就沒法保留界面上的資料了,
??對于Activity,手機發生橫豎屏切換時,Activity會被重新創建,同時存放在Activity中的資料也會丟失,這樣導致在某些場景下,需要撰寫大量保存和恢復資料的邏輯,
??Activity與ViewModel生命周期見下圖

ViewModel使用
補充:撰寫這個例子時,遇到的問題
- 無法使用sp.edit1語法糖,原因是AndroidStudio默認安裝jvm1.6進行編譯的,需要在module的build.gradle檔案中添加一下配置
android {
// ...
compileOptions {
sourceCompatibility = 1.8
targetCompatibility = 1.8
}
kotlinOptions {
jvmTarget = "1.8"
}
}
1.依賴庫
??如果沒有添加ViewModel依賴庫的,先添加下面依賴庫進行下載
在moudle的build.gradle中,添加下面依賴
dependencies {
//如果使用2.2.0以及以前的版本,則加載下面依賴庫,該依賴庫中有ViewModelProviders.of方法,會被標識為棄用狀態
implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
// 如果使用2.2.0之后版本,直接使用下面依賴庫,該依賴庫中沒有ViewModelProviders.of方法
implementation "androidx.lifecycle:lifecycle-process:2.2.0"
// 以上兩種依賴lifecycle-extensions 與 lifecycle-process選擇一種即可,
}

相關版本資料:lifecycle版本資訊,google.cn官方地址
2.創建ViewModel
??我們不可以直接創建ViewModel實體,要通過ViewModelProviders 或 ViewModelProvider進行創建
在"androidx.lifecycle:lifecycle-extensions:2.2.0"及以前版本中,可以 使用ViewModelProviders.of 方法,
viewModel = ViewModelProviders.of(“定義的Activity或者Fragment實體”).get(“定義的Model名稱”::class.java)
//例如:
class MainActivity : AppCompatActivity() {
lateinit var viewModel: MyMainViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
viewModel = ViewModelProviders.of(this).get(MyMainViewModel::class.java)
}
在"androidx.lifecycle:lifecycle-process:2.2.0"中, 沒有ViewModelProviders.of的創建方式,改為下面的方式進行創建,
viewModel = ViewModelProvider(“定義的Activity或者Fragment實體”,
ViewModelProvider.AndroidViewModelFactory.getInstance(application)).get(“定義的Model名稱”::class.java)
//例如:
class MainActivity : AppCompatActivity() {
lateinit var viewModel: MyMainViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
viewModel = ViewModelProvider(this,
ViewModelProvider.AndroidViewModelFactory.getInstance(application)).get(MyMainViewModel::class.java)
}
3.向ViewModel傳遞引數
??創建ViewModel實體時,我們無法通過建構式傳遞一些引數,ViewModel提供了ViewModelProvider.Factory來解決引數傳遞問題,這樣可以使用SharedPreferences實作退出程式之后再次打開時,資料仍然不會丟的效果,
創建一個實作了ViewModelProvider.Factory類,并在必須實作的create方法中創建自定義的ViewModel物件,以及需要傳遞的值,這樣就只需在創建ViewModel地時,再賦值一個自定義創建的ViewModelProvider.Factory引數即可,
//例如:
class MainViewModelFactory(private val countResume: Int) : ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
return MainViewModel(countResume) as T
}
}
4. 簡單例子
例子的效果是:點擊一次按鈕,改變界面上的文字,并在螢屏旋轉,退出程式后仍然可以記錄上次的文字狀態,以及重置文本內容的按鈕,
布局相關 : 一個文本,兩個按鈕
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
tools:context=".MainActivity">
<TextView
android:id="@+id/tv_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/btn_add_one"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Show"/>
<Button
android:id="@+id/btn_clear_num"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Reset"/>
</LinearLayout>
MainActivity類
import android.content.Context
import android.content.SharedPreferences
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.lifecycle.ViewModelProviders
import kotlinx.android.synthetic.main.activity_main.*
import androidx.core.content.edit as edit1
class MainActivity : AppCompatActivity() {
lateinit var viewModel: MainViewModel
lateinit var sp: SharedPreferences
val textList = listOf("1¥","2¥","3¥")
var count = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//創建SharedPreferences
sp = getPreferences(Context.MODE_PRIVATE)
val textResume = sp.getString("textResume","1¥")
viewModel = ViewModelProviders.of(this,MainViewModelFactory(textResume!!))
.get(MainViewModel::class.java)
btn_add_one.setOnClickListener {
count++
if (count > (textList.size - 1)){
count = 0
}
viewModel.text = textList[count]
updateUI()
}
btn_clear_num.setOnClickListener {
count = 0
viewModel.text = "1¥"
updateUI()
}
updateUI()
}
private fun updateUI() {
tv_content.text = viewModel.text
}
override fun onPause() {
super.onPause()
sp.edit1 {
putString("textResume",viewModel.text)
}
}
}
自定義ViewModel的類 MainViewModel
import androidx.lifecycle.ViewModel
class MainViewModel(textResume: String) : ViewModel() {
var text = textResume
}
自定義ViewModelProvider.Factory的類 MainViewModelFactory
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
class MainViewModelFactory(private val textResume: String) : ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
return MainViewModel(textResume) as T
}
}
覺得有幫助的點下贊喲,畢竟三連步驟更多,嘻嘻,謝謝大家的支持(* ^ ▽ ^ *)
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/241044.html
標籤:其他
