一、Activity 遇到的問題
Activity 遇到的問題 :
- 瞬態(tài)數(shù)據(jù)丟失 : 操作 Activity 時(shí) , 如果 屏幕 自動(dòng)旋轉(zhuǎn) , 當(dāng)前 Activity 組件會(huì) 執(zhí)行銷毀操作 , 并重新創(chuàng)建新的 Activity 組件 , 該操作會(huì) 導(dǎo)致 Activity 的 瞬態(tài)數(shù)據(jù) 丟失 ;
- 內(nèi)存泄漏 : 在 系統(tǒng)組件 如 Activity 中 , 啟動(dòng)了一個(gè)線程 , 在線程中執(zhí)行一系列操作 , 如果 Activity 在線程停止前銷毀 , 那么 從 Activity 銷毀 到 線程停止前 的這一段時(shí)間 , 就出現(xiàn)了內(nèi)存泄漏問題 ;
- 組件代碼量大 : 在 Activity 中寫了大量的代碼 , 導(dǎo)致 可維護(hù)性 降低 , 測試難度 增加 ;
二、視圖 View 和 數(shù)據(jù)模型 Model
在 Activity 中 , 存在兩種元素 , 視圖 View 和 填充視圖數(shù)據(jù)用的 數(shù)據(jù)模型 Model ;
如果將 視圖 和 數(shù)據(jù)模型 都寫在 Activity 中 , 二者 耦合程度很高 ,
此時(shí) , 就會(huì)造成上述 Activity 的三大問題 : ① 丟失瞬態(tài)數(shù)據(jù) , ② 內(nèi)存泄漏 , ③ 組件代碼量大 ;
三、ViewModel 架構(gòu)組件作用
為了解決上述問題 , 提出了 ViewModel 架構(gòu)組件 ,
該組件 是 視圖 View 和 數(shù)據(jù)模型 Model 之間 的 溝通橋梁 ;
借助 ViewModel , 視圖 與 數(shù)據(jù)模型 實(shí)現(xiàn)了 解耦 , 同時(shí) 還能保證 視圖 與 數(shù)據(jù)模型 之間 保持 通信 ;
這樣 Activity 的代碼量減少了 , 只需要維護(hù) 視圖 View 相關(guān)內(nèi)容 , 增加了代碼的可維護(hù)性 , 以及可測試性 ;
在 ViewModel 架構(gòu)中 , 數(shù)據(jù) 不由 View 直接進(jìn)行管理 , 而是 由 ViewModel 進(jìn)行管理 ;
當(dāng) Activity 屏幕旋轉(zhuǎn) , 銷毀時(shí) , 只會(huì)銷毀 Activity 組件 , 不會(huì)將 ViewModel 以及 數(shù)據(jù)模型 Model 銷毀 ;
Activity 中的組件 獲取數(shù)據(jù)時(shí) , 不直接從 數(shù)據(jù)模型 Model 中獲取 , 而是 從 ViewModel 架構(gòu)組件中獲取 ;
ViewModel 作用 :
- 保存瞬態(tài)數(shù)據(jù)
- 作為 View 視圖 與 Model 數(shù)據(jù)模型 的橋梁
- 作為 不同的 Activity 或 Fragment 之間溝通的橋梁
四、ViewModel 代碼示例
1、ViewModel 視圖模型
ViewModel 視圖模型 繼承 androidx.lifecycle.ViewModel 類 , 在其中定義要維護(hù)的數(shù)據(jù)即可 ;
代碼示例 :文章來源:http://www.zghlxwxcb.cn/news/detail-823523.html
package kim.hsl.viewmodeldemo
import androidx.lifecycle.ViewModel
class MyViewModel : ViewModel() {
var number: Int = 0
}
2、Activity 組件
在 Activity 中 , 要 綁定 ViewModel 組件 , 通過 ViewModelProvider 獲取 MyViewModel::class.java 類 對(duì)應(yīng)的 ViewModel 實(shí)例對(duì)象 ;
代碼示例 :
package kim.hsl.viewmodeldemo
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.TextView
import androidx.lifecycle.ViewModelProvider
class MainActivity : AppCompatActivity() {
lateinit var textView: TextView
lateinit var myViewModel: MyViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// 獲取布局組件
textView = findViewById(R.id.textView)
// 獲取 ViewModel
myViewModel = ViewModelProvider(this,
ViewModelProvider.AndroidViewModelFactory(application))
.get(MyViewModel::class.java)
// 組件中顯示 ViewModel 中的內(nèi)容
textView.setText("${myViewModel.number}")
}
fun onClick(view: View) {
myViewModel.number++
textView.setText("${myViewModel.number}")
}
}
3、UI 布局文件
點(diǎn)擊按鈕 , 令顯示的文本數(shù)字自增 ;
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0"
android:textSize="40sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.3" />
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="數(shù)值自增"
android:textSize="40sp"
android:onClick="onClick"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.5" />
</androidx.constraintlayout.widget.ConstraintLayout>
4、運(yùn)行效果
在屏幕旋轉(zhuǎn)后 , Activity 銷毀重建 , 也沒有影響數(shù)據(jù)運(yùn)行 , 自增操作沒有被打斷 ;
五、ViewModel 生命周期
ViewModel 的 生命周期 與 Activity 或 Fragment 的 生命周期 相互獨(dú)立 , ViewModel 不受 Activity 組件銷毀的影響 ;
如果 由于 屏幕旋轉(zhuǎn) 原因 導(dǎo)致的 Activity 銷毀重建 , 與之綁定的 ViewModel 會(huì)在銷毀時(shí)解綁 , Activity 重建時(shí)重新綁定 ;
ViewModel 會(huì)在 應(yīng)用生命周期 內(nèi)存活 , 并且可以在 Activity 或 Fragment 之間共享數(shù)據(jù) ;
ViewModel 的 生命周期 : 一個(gè) ViewModel 實(shí)例對(duì)象 可以與 多個(gè) Activity 或 Fragment 綁定 ;
- 創(chuàng)建 : 在 Activity 的 首次啟動(dòng)時(shí) 創(chuàng)建 ViewModel 實(shí)例對(duì)象 , 如果 Activity 多次啟動(dòng) , ViewModel 只會(huì)創(chuàng)建一次 ;
- 綁定 : Activity 與 ViewModel 關(guān)聯(lián)時(shí) , 開始綁定 ViewModel , Activity 組件中 綁定 ViewModel 代碼如下 ;
// 獲取 ViewModel
myViewModel = ViewModelProvider(this,
ViewModelProvider.AndroidViewModelFactory(application))
.get(MyViewModel::class.java)
- 解綁 : 當(dāng) Activity 或者 Fragment 被銷毀時(shí) , 與之綁定的 ViewModel 會(huì)與 UI 組件解綁 ;
- 銷毀 : ViewModel 關(guān)聯(lián)的所有的 Activity 或 Fragment 全部銷毀 , 則 ViewModel 實(shí)例對(duì)象 也會(huì)被銷毀 ;
六、ViewModel 使用注意事項(xiàng)
ViewModel 使用注意事項(xiàng) :
使用 ViewModel 時(shí) , 不要將 Context 上下文對(duì)象傳入 ViewModel 中 , 否則會(huì)導(dǎo)致內(nèi)存泄漏 ;
如果要使用 Context 上下文對(duì)象 , 則 ViewModel 需要繼承 AndroidViewModel 類 , 在 其構(gòu)造函數(shù) 中獲取 Application 對(duì)象 ;
代碼示例 :
package kim.hsl.viewmodeldemo
import android.app.Application
import androidx.lifecycle.AndroidViewModel
class MyViewModel2 : AndroidViewModel {
constructor(application: Application) : super(application) {
// 此處可獲取 Application 上下文對(duì)象
}
}
博客代碼 :文章來源地址http://www.zghlxwxcb.cn/news/detail-823523.html
- GitHub : https://github.com/han1202012/ViewModelDemo
- CSDN : https://download.csdn.net/download/han1202012/87541442
到了這里,關(guān)于【Jetpack】ViewModel 架構(gòu)組件 ( 視圖 View 和 數(shù)據(jù)模型 Model | ViewModel 作用 | ViewModel 生命周期 | 代碼示例 | 使用注意事項(xiàng) )的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!