導航:首頁 > 操作系統 > androidfragment單例

androidfragment單例

發布時間:2025-03-28 08:22:03

Ⅰ Android-ViewModel原理解析

在這四個方法中,其實唯一的區別就是要不要傳Factory,當沒有傳自定義的Factory的時候,則會傳入默認的Factory,我們看ViewModelProvider構造器的源碼和部分of方法的源碼:

在ViewModelProvider中需要傳入一個VieModelStore對象,這個對象是由ViewModelStoreOwner來提供的,而在Activity或者Fragment中,是由Activity和Fragment來提供的,因為ViewModelStoreOwner是一個介面,而AppCompatActivity的祖父ComponentActivity和Fragment均實現了ViewModelStoreOwner介面。

但是ViewModelProviders在新的lifecycle-extensions庫中,已經是屬於被棄用的。新版的API直接使用ViewModelProvider,而不是ViewModelProviders。
比如:

可以如下的方式在baseActivity中添加,由子類Activity調用:

創建ViewModel對象,首先就需要先初始化一個ViewModelProvider對象

可以看出,ViewModelProvider構造函數其實最終都是需要兩個參數,一個是ViewModelStoreOwner對象,一個是Factory。而ViewModelStoreOwner其實就是用來獲取一個ViewModelStore對象來保存ViewModel對象的。而Factory就是用來創建ViewModel對象的。

這個介面的主要實現的作用就是返回一個ViewModelStore對象。在Android中,Activity和Fragment都會實現該介面,並且實現getViewModelStore()方法。
比如Activity就是在FragmentActivity的父類ComponentActivity中實現了ViewModelStoreOwner介面

Fragment的ViewModelStore其實是由FragmentManager進行管理獲取

每個FragmentActivity都會有一個自己的FragmentManager對象,所以每個FragmentManagerViewModel對象,管理的是一個FragmentActivity中的所有的Fragment對應的ViewModel。具體看FragmentManagerViewModel的getViewModelStore方法

從這里可以看出,每個Fragment都會有自己的ViewModelStore對象,而ViewModelStore對象,是根據每個Fragment的唯一標識進行創建的。

ViewModelStore類對象,是每個Activity或者Fragment都有一個,目的是用於保存該頁面的ViewModel對象,方便ViewModel的管理

從ViewModelProvider的get方法中,可以看出,get方法傳入的是一個ViewModel.class的Class類型,然後通過這個類型,得到ViewModel的規范名稱。將ViewModel對象緩存在ViewModelStore中的HashMap中。而ViewModel的創建,其實是通過ViewModelProvider.Factory來實現的

ViewModelProviders的of方法,用於返回一個ViewModelProvider對象

從這里我們可以看到,如果傳入的Activity或者Fragment有方法實現,而factory為null的時候,則會通過創建對應的Factory,而如果沒有的實現,那麼就會調用NewInstanceFactory來創建對應的Factory,而NewInstanceFactory其實就是創建AndroidViewModelFactory對象。
最終ViewModel對象,其實就是通過AndroidViewModelFactory的create的方法實現來創建。一般就是通過Class.newInstance或者Class.getConstructor來創建對象。

而ViewModelProvider的第一個參數,其實最終傳入的是ViewModelStore對象,這個對象內部是通過一個HashMap來保存ViewModel對象
而新版的源碼,ViewModelStore對象是通過Fragment和FragmentActivity對象的getViewModelStore方法來獲取,而原先的HolderFragment的功能都移植到了Fragment中

HolderFragment通過設置setRetainInstance(true),使得自身能夠不受到屏幕旋轉等configuration
changes影響而存活,直到依附的Activity正常結束。
因為HolderFragment的生命周期,ViewModelStore對象保存在HolderFragment中,而ViewModel又存儲在ViewModelStore中,這就是為什麼我們說ViewModel類能夠讓數據在屏幕旋轉等配置信息改變導致UI重建的情況下不被銷毀。

ViewModelProvider的get方法:

在ViewModel中,有兩種Factory,Factory是的類型是由ViewModelProvider在初始化的時候創建的,所以是由ViewModelProvider決定Factory的類型。在ViewModelProvider中,有兩種Factory,一種是默認的Factory,默認的Factory是通過在ComponentActivity或者Fragment中實現介面,然後在()方法中初始化一個SavedStateViewModelFactory對象;另一種Factory則是NewInstanceFactory,這種是通過NewInstanceFactory.getInstance()的單例方式獲取。

其實就是通過ViewModel的Class對象,然後通過反射創建ViewModel對象,然後保存到ViewModelStore中的Map集合中
從ViewModelProvider的get方法可以看出,在ViewModelProvider的get方法中會根據Factory的類型,進行不同方法的調用。SavedStateViewModelFactory是實現了ViewModelProvider.KeyedFactory介面的,所以在創建ViewModel的時候,調用的是SavedStateViewModelFactory的create方法。

AndroidViewModel和ViewModel的構造器參數Class

ViewModel保存和恢復數據
ComponentActivity和Fragment都將數據的保存和恢復邏輯轉發給了SavedStateRegistryController。在在onCreate方法里通過調用performRestore來恢復數據,在onSaveInstanceState方法里通過調用performSave來保存數據。而SavedStateRegistryController中的SavedStateRegistry對象,就是實際進行數據的保存和恢復的,在SavedStateRegistry通過唯一的key獲取到一個SavedStateProvider,而SavedStateProvider其實就是返回需要保存的數據,將對應的需要緩存的數據一一返回,然後保存在系統緩存時的回調到onSaveInstanceState的方法參數Bundle中進行保存。
SavedStateRegistry.performSave()
該方法是由ComponentActivity的onSaveInstanceState方法觸發調用SavedStateRegistryController的performSave,進而調用的

在SavedStateRegistry恢復數據的時候,會把恢復後的數據都交給SavedStateHandle。希望保留的數據,可以通過兩種方式向mRegular保存數據。

在ComponentActivity恢復數據的時候,會通過SavedStateRegistryController.performSave在Activity的onSaveInstanceState方法中進行數據的保存,然後在ComponentActivity的onCreate方法中,通過調用SavedStateRegistryController.performRestore方法進行數據的恢復,這些恢復的數據都會保存在SavedStateHandleController對象中的SavedStateHandle屬性中,然後在Activity重新創建的時候,會通過反射創建對應的ViewModel對象的時候,將SavedStateHandleController中的SavedStateHandle賦值給對應的ViewModel進行數據恢復。

這塊的源碼分析可以參考:
從源碼看 Jetpack(7)-SavedStateHandle源碼詳解

這里其實就是直接使用Class的newInstance直接創建對象。Activity和Fragment一般都是使用SavedStateViewModelFactory創建ViewModel對象。

ViewModel的銷毀,要分為Activity和Fragment兩部分。
首先看下ViewModel在銷毀的時候做的事情

而ViewModel的clear()方法的調用,是在ViewModelStore中

Activity的銷毀,是通過Lifecycle監聽生命周期回調,當生命周期執行到onDestroy的時候,調用ViewModelStore的clear()方法進行ViewModel的銷毀。
看ComponentActivity中構造器中的實現:

Fragment的生命周期管理,如下:

Fragment的生命周期,首先會依次增大,然後在從onResume變成onPause的時候,就開始狀態碼減小。即先升再降的一個狀態變化。在當前狀態碼變成CREATED的時候,就會執行onDestroy。即調用

FragmentStateManager.destroy

在這里就會調用nonConfig.clearNonConfigState方法,nonConfig其實就是FragmentManagerViewModel對象。
FragmentManagerViewModel.clearNonConfigState

按照上面的邏輯,在Activity重建時會執行destory生命周期事件,那麼為什麼ViewModel沒有銷毀呢?
其實就是在屏幕旋轉的時候,AMS通過Binder回調Activity的()方法,這個時候就會進行數據的保存,保存到一個NonConfigurationInstances對象;而在屏幕翻轉結束之後,會再一次調用ViewModelProvider的構造函數,此時就會調用owner.getViewModelStore(),接著就會調用(),這里就會通過Activity中的NonConfigurationInstances對象取出保存的ViewModelStore對象。
所以數據保存就是通過()方法保存在NonConfigurationInstances對象,而再一次使用取出ViewModel的數據的時候,就是從nc對象中取出ViewModelStore對象,而ViewModelStore對象保存有ViewModel集合
通過對ComponentActivity的getViewModelStore()方法進行分析。可以找到這個問題的答案。

當mViewModelStore為null的時候,會從NonConfigurationInstances中獲取ViewModelStore對象。
其實在ComponentActivity和Activity中都會有一個NonConfigurationInstances類,而Activity中的NonConfigurationInstances類結構如下:

這里的Object activity其實就是保存的ComponentActivity中的NonConfigurationInstances類對象,看Activity的下面的方法:

activity這個Object對象,其實是通過()方法返回值賦值,而()方法的實現是在ComponentActivity中。
看ComponentActivity中的下面方法:

因為這里會在ComponentActivity中的NonConfigurationInstances類對象中保存ViewModelStore對象,所以這也是Activity重建時不會銷毀ViewModel的原因。

()方法除了被Activity的()調用以外,還會被LocalActivityManager的()方法調用

在分析ViewModel的銷毀過程時,我們看到Activity與Fragment存儲VieModel是分離的,那麼同一個Activity下的Fragment是如何共享ViewModel的呢?
其實共享的是Activity的ViewModel。

而具體的實現邏輯,其實就是在FragmentViewModelLazy.kt中的:

在Fragment中可以直接調用,這是一個Fragment的擴展函數,通過實現requireActivity().viewModelStore,獲取到了Activity的ViewModelStore對象後,這樣就可以實現了Fragment共用Activity的ViewModel,從而實現了Fragment之間共享ViewModel。
Fragment之間共享ViewModel,需要引入

Ⅱ Android大廠面試經驗分享(OPPO,位元組,華為,阿里)

我是從小公司跳出來的,最終入職OPPO,說實話這段時間的經歷讓我深深地感受到,我們為跳槽做的一些臨時抱佛腳的提升跟那些大佬的沉澱比起來太渺小了。我們都知道找資料學習、刷面試題,但也許只能應付這一次的面試,後面還是會技術發愁,那些短時間背下來的東西遲早會忘掉, 大家還是做好長期提升自己的准備,好好沉澱的東西最後才是屬於自己的。

說說當時的面試過程,我是內推獲得的面試機會,很感謝當時幫我內推的兄弟,總共三輪面試,兩輪技術,一輪HR面,當天面試結束。

我10:10分到的公司,10:30開始面試,第一輪面試將近一個小時,聊的點我基本上都答得上來,自我感覺良好。然後面試官讓我等一下,他去叫他們老大來給我二面,我等了有二十幾分鍾吧,二面有一個多小時,這次問的比較深,有些地方答的有些嗑吧,總體來說我自己是滿意的。HR面約到下午了,整個流程下來每輪面試官都讓人感覺很不錯,我自己做的准備也讓我面試感覺下來很爽。

我把面試遇到過的以及自己學慣用到過相關內容都整理到一起了,方便自己進行復盤和後續的查漏補缺:

一、 java基礎

1.1 靜態內部類和非靜態內部類的比較

1.2 多態的理解與應用

1.3 java方法的多態性理解

1.4 java中介面和繼承的區別

1.5 線程池的好處,詳解,單例(絕對好記)

1.6 線程池的優點及其原理

1.7 線程池的優點(重點)

1.8 為什麼不推薦通過Executors直接創建線程池

1.9 不怕難之BlockingQueue及其實現

1.10 深入理解ReentrantLock與Condition

1.11 Java多線程:線程間通信之Lock

1.12 Synchronized 關鍵字原理

1.13 ReentrantLock原理

1.14 HashMap中的Hash沖突解決和擴容機制

1.14 Java並發

1.15 Java虛擬機

1.16 JVM常見面試題

1.17 JVM內存結構

1.18 類載入機制/雙親委託

二、 Android基礎

2.1 Activity知識點(必問)

2.2 Fragment知識點

2.3 Service知識點

2.4 Intent知識點

2.5 數據存儲

三、UI控制項篇

3.1 屏幕適配

3.2 主要控制項優化

3.3 事件分發與嵌套滾動

3.4 動態化頁面構建方案

四、網路通信篇

4.1 網路協議

五、架構設計篇

5.1 MVP架構設計

5.2 組件化架構

六、性能優化篇

6.1 啟動優化

6.2 內存優化

6.3 繪制優化

6.4 安裝包優化

七、源碼流程篇

7.1 開源庫源碼分析

7.2 Glide源碼分析

7.3 day 20 面試題:Glide面試題

7.4 聊一聊關於Glide在面試中的那些事

7.5 面試官:簡歷上如果寫Glide,請注意以下幾點…

7.6 Glide OOM問題解決方法匯總

7.7 LeakCanary源碼分析

7.8 OkHttp源碼分析

7.9 okhttp連接池復用機制

7.10 okhttp 流程和優化的實現

7.11 一篇讓你受用的okhttp分析

7.12 OkHttp面試之–OkHttp的整個非同步請求流程

7.13 OkHttp面試之–HttpEngine中的sendRequest方法詳解

7.14 OkHttp解析大總結

7.15 Okhttp任務隊列工作原理

7.16 Android高頻面試專題 - 架構篇(二)okhttp面試必知必會

7.17 Android 網路優化,使用 HTTPDNS 優化 DNS,從原理到 OkHttp 集成

7.18 Retrofit源碼分析

7.19 RxJava源碼分析

7.20 RxJava原理與源碼分析

7.21 RxJava如何進行線程切換的?

7.22 Rxjava內存泄漏防止方案——RxLifecycle,AutoDispose,RxLife框架

7.23 Tinker源碼分析

7.24 ARouter源碼分析

7.25 Android框架層源碼解析

7.26 演算法設計

八、新技術篇

8.1 實戰問題篇

九、面試篇

9.1 開源文檔

9.2 面試文獻

以上就是我的學習和面試積累,有自己面試經歷過的,也有整理的一些大廠面試題,篇幅有限,具體內容就不展示了,我已經整理成文檔了。

還是開頭說的,僅靠面試期間臨時抱佛腳和刷題對自身發展不是長久之計,做好長期提升的規劃,好好沉澱每一次的學習和面試經歷,把這些最終都轉化成屬於自己的東西才是實質上對自己最有用的。

Ⅲ 如何設計app的架構

想要設計App的整體框架,首先要清楚我們做的是什麼

一般我們與網路交互數據的方式有兩種:主動請求(http),長連接推送

結合網路交互數據的方式來說一下我們開發的App的類型和特點:

閱讀全文

與androidfragment單例相關的資料

熱點內容
pythonapriori演算法實現 瀏覽:410
高效學習法pdf 瀏覽:785
投資的書籍哪個app可以看 瀏覽:833
phpmysql經緯度 瀏覽:210
u盤自帶的文件夾怎麼刪除 瀏覽:605
無法檢測伺服器的dns地址 瀏覽:306
quartus如何編譯一個文件 瀏覽:235
工程之星50編碼文件夾 瀏覽:75
程序員軟體著作權中的翻譯權 瀏覽:257
phpsession例子 瀏覽:886
華為路由器查看連接ip命令 瀏覽:224
四個程序員開發一款小游戲 瀏覽:801
程序員猝死知乎 瀏覽:119
安卓如何設置鎖屏壁紙自動更換 瀏覽:754
mp3壓縮比例 瀏覽:166
mc伺服器如何製作輔助登錄提示 瀏覽:191
哪個醫療app好 瀏覽:337
電冰箱鎖單片機課程設計 瀏覽:776
單片機的振盪頻率為61mhz 瀏覽:78
得物app上的游戲在哪裡 瀏覽:739