viewmodel創建及使用分析

1、相關的類

  • ViewModelStore :管理viewModel實例,內部包含一個Map用來存儲viewmodel,內部包括put、get、clear等方法
  • ViewModelProvider :管理ViewModelStore和Factory,Factory里面有create方法是創建對應的viewmodel的,ViewModelProvider內部有一個get方法獲取viewmodel

2、在項目中應用

首先新建項目分別創建TestViewModel
TestViewModel.class

fun provideFactory(repository: TestRepository): ViewModelProvider.Factory = object : ViewModelProvider.Factory {@Suppress("UNCHECKED_CAST")override fun <T : ViewModel> create(modelClass: Class<T>): T {return TestViewModel(repository) as T}}

MainActivity.class中初始化代碼:

    private val testViewModel by viewModels<TestViewModel> {TestViewModel.provideFactory(TestRepository())}

接下來在MainActivity里面就可以正常使用這個viewmodel了

3、流程簡單解析

首先我們在mainActivity里面初始化時候使用了by viewmodel 這個方式進行初始化點擊進入這個方法之后源碼如下:

public inline fun <reified VM : ViewModel> ComponentActivity.viewModels(noinline extrasProducer: (() -> CreationExtras)? = null,noinline factoryProducer: (() -> Factory)? = null
): Lazy<VM> {val factoryPromise = factoryProducer ?: {defaultViewModelProviderFactory}return ViewModelLazy(VM::class,{ viewModelStore },factoryPromise,{ extrasProducer?.invoke() ?: this.defaultViewModelCreationExtras })
}

可以看到viewModels是ComponentActivity的一個擴展函數,參數需要傳factoryProducer,factoryProducer就是前面我們提到過的ViewModelProvider的內部的一個factory類,用來創建viewModel的,所以我們傳入TestViewModel.provideFactory。
繼續向下看進入ViewModelLazy:

public class ViewModelLazy<VM : ViewModel> @JvmOverloads constructor(private val viewModelClass: KClass<VM>,private val storeProducer: () -> ViewModelStore,private val factoryProducer: () -> ViewModelProvider.Factory,private val extrasProducer: () -> CreationExtras = { CreationExtras.Empty }
) : Lazy<VM> {private var cached: VM? = nulloverride val value: VMget() {val viewModel = cachedreturn if (viewModel == null) {val factory = factoryProducer()val store = storeProducer()ViewModelProvider(store,factory,extrasProducer()).get(viewModelClass.java).also {cached = it}} else {viewModel}}override fun isInitialized(): Boolean = cached != null
}

首先判斷是否有緩存,如果有緩存直接返回,無緩存情況下就去ViewModelProvider獲取對應的viewmodel并且進行一下緩存操作,接下來我們看一下ViewModelProvider的get方法

    public open operator fun <T : ViewModel> get(key: String, modelClass: Class<T>): T {val viewModel = store[key]if (modelClass.isInstance(viewModel)) {(factory as? OnRequeryFactory)?.onRequery(viewModel!!)return viewModel as T} else {@Suppress("ControlFlowWithEmptyBody")if (viewModel != null) {// TODO: log a warning.}}val extras = MutableCreationExtras(defaultCreationExtras)extras[VIEW_MODEL_KEY] = key// AGP has some desugaring issues associated with compileOnly dependencies so we need to// fall back to the other create method to keep from crashing.return try {factory.create(modelClass, extras)} catch (e: AbstractMethodError) {factory.create(modelClass)}.also { store.put(key, it) }}

get方法通過內部的store傳入類名來獲取view model,那么store是從哪里來的呢?往回看能看到是在ComponentActivity.viewModels這里返回了一個ViewModelLazy時傳入了viewModelStore,這個viewModelStore是從ComponentActivity初始化時候就創建了的

    public ComponentActivity() {//......getLifecycle().addObserver(new LifecycleEventObserver() {@Overridepublic void onStateChanged(@NonNull LifecycleOwner source,@NonNull Lifecycle.Event event) {if (event == Lifecycle.Event.ON_DESTROY) {// Clear out the available contextmContextAwareHelper.clearAvailableContext();// And clear the ViewModelStoreif (!isChangingConfigurations()) {getViewModelStore().clear();}mReportFullyDrawnExecutor.activityDestroyed();}}});getLifecycle().addObserver(new LifecycleEventObserver() {@Overridepublic void onStateChanged(@NonNull LifecycleOwner source,@NonNull Lifecycle.Event event) {ensureViewModelStore();getLifecycle().removeObserver(this);}});//......}void ensureViewModelStore() {if (mViewModelStore == null) {NonConfigurationInstances nc =(NonConfigurationInstances) getLastNonConfigurationInstance();if (nc != null) {// Restore the ViewModelStore from NonConfigurationInstancesmViewModelStore = nc.viewModelStore;}if (mViewModelStore == null) {mViewModelStore = new ViewModelStore();}}}

在activity創建時添加生命周期監聽,生命周期變更時創建ViewModelStore,當生命周期destory時會通過isChangingConfigurations來判斷是否是通過切換橫豎屏導致的destroy,如果是的話不會對view model執行clear,這樣保證了view model在切換橫豎屏時依然可以保存數據,等頁面真正的退出執行的destroy時才會對viewmodel執行clear方法,這樣保證了viewmodel的生命周期和activity一致,也不需要我們單獨對其生命周期進行維護。

針對這個流程簡單的分析,如有分析不符的地方歡迎評論指正

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/44923.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/44923.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/44923.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Facebook的未來藍圖:從元宇宙到虛擬現實的跨越

隨著科技的不斷演進和社會的數字化轉型&#xff0c;虛擬現實&#xff08;VR&#xff09;和增強現實&#xff08;AR&#xff09;作為下一代計算平臺正逐漸走進人們的視野。作為全球領先的科技公司之一&#xff0c;Facebook正在積極探索并推動這一領域的發展&#xff0c;以實現其…

嫌云服務器太貴,使用內網穿透代替

企業與個人開發者常常面臨一個現實問題&#xff1a;高昂的云服務器成本。隨著業務需求的增長&#xff0c;持續的服務器租賃費用可能成為負擔。然而&#xff0c;在這個充滿創新的時代&#xff0c;一種名為“內網穿透”的技術正逐漸成為解決這一難題的優選方案。本文將探討內網穿…

深度學習基礎與實戰:Python實現

深度學習基礎與實戰&#xff1a;Python實現 深度學習是機器學習的一個重要分支&#xff0c;通過多層神經網絡實現對數據的自動特征提取和建模。本文將介紹深度學習的基礎概念、常用框架以及一個完整的實戰項目&#xff0c;幫助讀者從基礎入門到實際應用。 目錄 深度學習概述…

CF 1986D. Mathematical Problem

原題鏈接&#xff1a;Problem - 1986D - Codeforces 題意&#xff1a;一串長度最多為20的由數字組成的字符串&#xff0c;在這些數字中間可以添加字符串長度減去二數量的符號&#xff0c;加或者乘&#xff0c;例如1234&#xff0c;就可以添加加號或者乘號二個&#xff0c;變成…

vue中el-table前端導出excel數據表格

一、el-table為正常時&#xff0c;導出方法如下&#xff1a; 1.添加導出按鈕 <el-button class"greenLinearbg dc" size"small" click"webExportTotalExcel()" v-if"totalBillShow">導出</el-button>2.導出方法 // we…

Spring開發實踐(二)

EnableAsync 和 Async 注解的使用方法 EnableAsync 和 Async 是Spring框架中的兩個注解&#xff0c;用于啟用和使用異步方法執行。它們可以幫助你在Spring應用程序中實現異步編程&#xff0c;從而提高應用程序的性能和響應速度。 EnableAsync EnableAsync 注解用于啟用Sprin…

ARM Ubuntu 主機安裝指定版本Python

要在你的ARM Linux主機上安裝Python 3.12&#xff0c;你可以從源碼編譯安裝。以下是具體步驟&#xff1a; 步驟1&#xff1a;安裝依賴 首先&#xff0c;確保你有必要的編譯工具和依賴包&#xff1a; sudo apt-get update sudo apt-get install -y build-essential libssl-d…

【每日一練】python的類.對象.成員.行為.方法傳參綜合實例(保姆式教學)

運行結果: 本節課程內容&#xff1a;類的使用 1.掌握類的定義和使用方法 2.掌握類的成員的方法使用 3.掌握self關鍵字的作用 4.定義在類里的函數是類的一種行為&#xff0c;叫方法 5.帶傳參的行為使用方法 類基本分兩部分組成&#xff1a;1.屬性,2.方法 類的使用語法&#xf…

springCloud整合Dubbo案例

前言&#xff1a; 好久沒有使用dubbo了&#xff0c;溫習一下。 一、先搭建一個SpringCloud框架 整體框架如下圖 1. 先創建一個父工程&#xff1a; <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4…

開發者必讀:獲取電商API的多種渠道

開發電商軟件往往需要對接電商API&#xff0c;電商API可以從哪些渠道獲取&#xff1f;下面給大家介紹兩種獲取渠道。 一、從電商平臺開放平臺獲取電商API 電商平臺的開放平臺是獲取電商API最直接的渠道&#xff0c;但是電商平臺較多&#xff0c;每一個電商平臺都需要單…

Vue3 引入騰訊地圖 包含標注簡易操作

1. 引入騰訊地圖API JavaScript API | 騰訊位置服務 (qq.com) 首先在官網注冊賬號 并正確獲取并配置key后 找到合適的引入方式 本文不涉及版本操作和附加庫 據體引入參數參考如下圖 具體以鏈接中官方參數為準標題 在項目根目錄 index.html 中 寫入如下代碼 <!-- 引入騰…

Socks5代理為什么比HTTP代理快?

在數字化日益深入的時代&#xff0c;網絡安全和隱私保護成為了公眾關注的焦點。為了應對網絡威脅&#xff0c;保護個人隱私和數據安全&#xff0c;代理技術應運而生。在眾多代理協議中&#xff0c;SOCKS5代理和HTTP代理是兩種較為常見的選擇。然而&#xff0c;為何SOCKS5代理在…

網頁設計零基礎入門:前端技術全攻略

在當今互聯網飛速發展的時代&#xff0c;前端網頁設計已經成為一個備受關注的領域。隨著其重要性的不斷提高&#xff0c;越來越多的專業人士和愛好者開始對前端設計感興趣&#xff0c;希望通過掌握這項技術開辟自己的職業道路。然而&#xff0c;對于新手設計師來說&#xff0c;…

ollama + lobechat 搭建自己的多模型助手

背景 人工智能已經推出了快2年了&#xff0c;各種模型和插件&#xff0c;有漸漸變成熟的趨勢&#xff0c;打造一個類似 hao123網站的人工智能模型入口&#xff0c;也變得有需求了。用戶會去比較多個ai給出的答案&#xff0c;作為程序員想擁有一臺自己的GPU服務器來為自己服務。…

如何在vue的項目中導入阿里巴巴圖標庫

阿里巴巴矢量圖標庫官網&#xff1a;iconfont-阿里巴巴矢量圖標庫 選擇你喜歡的圖標&#xff0c;添加入庫 點擊添加至項目&#xff0c;并新建文件夾&#xff0c;點擊確定 選擇font-class&#xff0c;點擊生成代碼 代碼生成后&#xff0c;在網站上打開 全選復制到style 點擊復制…

【TB作品】MSP430F6638單片機,頻率計

基于 MSP430-FFTB6638 實驗箱 頻率測量與通信系統 利用 MCU 定時器模塊相關功能設計實現數字頻率計功能&#xff0c;測量范圍&#xff1a;100~10000Hz&#xff0c; 測量誤差≤1%&#xff0c;測量速度≤1 秒。測量結果本地顯示&#xff08;段式 LCD、字符型 LCD、點陣 LCD &…

springboot系列九: 接收參數相關注解

文章目錄 基本介紹接收參數相關注解應用實例PathVariableRequestHeaderRequestParamCookieValueRequestBodyRequestAttributeSessionAttribute 復雜參數基本介紹應用實例 自定義對象參數-自動封裝基本介紹應用實例 基本介紹 1.SpringBoot 接收客戶端提交數據 / 參數會使用到相…

【小白也能看的懂】想要玩轉AI大模型,這4招你得知道

前言 對于大部分人來說&#xff0c;能夠靈活使用AI工具&#xff0c;并對自己每個常用的AI工具優劣勢很清楚&#xff0c;就已經足夠了。不過&#xff0c;畢竟AI發展實在太快&#xff0c;多了解一些相關的知識點&#xff0c;以全局的視角去看AI&#xff0c;可以避免管中窺豹&…

編程語言現狀:深入剖析與未來展望

編程語言現狀&#xff1a;深入剖析與未來展望 在數字化時代的浪潮中&#xff0c;編程語言作為信息科技領域的基石&#xff0c;正經歷著前所未有的變革與發展。本文將從四個方面、五個方面、六個方面和七個方面&#xff0c;深入剖析編程語言的現狀&#xff0c;并展望其未來的發…

【錯題集-編程題】買賣股票的最好時機(四)(動態規劃)

力扣對應題目鏈接&#xff1a;188. 買賣股票的最佳時機 IV - 力扣&#xff08;LeetCode&#xff09; 牛客對應題目鏈接&#xff1a;買賣股票的最好時機(四)_牛客題霸_牛客網 (nowcoder.com) 一、分析題目 1、狀態表示 為了更加清晰的區分買入和賣出&#xff0c;我們換成有股…