以默認activity的配置 在屏幕旋轉的時候,通常activty都會被重建,以這個狀況爲例子來講明 Bundle savedInstanceState 和 fragment.setRetainInstance 以及 viewmodel的區別c++
做者github :github.com/zjw-swun 歡迎相互關注git
Bundle savedInstanceState 和 fragment.setRetainInstance 以及 viewmodel(viewModel = ViewModelProviders.of(this).get(UserProfileViewModel.class);用法而不是本身new的那種),都具有一種功能,就是當 屏幕旋轉的時候( 以默認activity的配置前提),都能保存一些要被銷燬掉的activity中的一些數據(如editext文本,以及recyclerView的滑動位置等),那麼這3個有什麼區別嗎,會不會由於咱們不知道原理而踩坑,下文給出答案。github
Bundle savedInstanceState
中的數據是由系統進程進行存儲的,它能存儲的數據容量大小有限
(例如intent中若是傳輸Bundle內容過大會出現異常),可是好比本身app由於手機內存不足而殺掉進程的話,能夠可以
利用該方式進行數據還原 2.fragment.setRetainInstance
以及viewmodel
(viewModel = ViewModelProviders.of(this).get(UserProfileViewModel.class);用法而不是本身new的那種)的原理是同樣的,都是利用,Activity類的NonConfigurationInstances
類在app進程中進行保存的,它能存儲數據容量比Bundler savedInstanceState 方式要大
,可是好比本身app由於手機內存不足而殺掉進程的話,則不能
用該方式進行數據還原如下以activity類中NonConfigurationInstances類如何在屏幕旋轉的時候( 以默認activity的配置前提)如何存儲並恢復NonConfigurationInstances對象爲例,剖析原理 如下截圖以及截圖中的代碼api版本爲28,運行環境官方api 28的模擬器上 測試代碼就不貼了很簡單, 先貼一下debug斷點列表,有興趣能夠試試,至於如何debug app以及debug系統進程,不知道的朋友能夠看一下我另外一篇文章https://www.imooc.com/article/21992
廢話很少說 放圖api
而後看重建activity時候的斷點(截圖中截的是被殺死的activity 走到ondestroy的時候)bash
這裏說明一下上一個activty先走ondrstroy 而後才重建新的activity這裏和activity跳轉作一個區分,而後從上圖中能夠發現被殺死的activity 走到ondestroy的時候中的r
和重建時候傳入的參數
r
(ActivityThread類中的ActivityClientRecord類型)是同一個對象,看看一下這個ActivityClientRecord類的代碼
static final class ActivityClientRecord {
//...不重要參數
Activity.NonConfigurationInstances lastNonConfigurationInstances;
//...不重要參數;
}
複製代碼
這就是核心的原理代碼了,那麼爲何說是存儲在app進程中呢,根據斷點列表你會發現涉及到一個關鍵類叫作 ActivityRelaunchItem
這個類 app
mActivityClientRecord
就是app進程存儲的那個
r
了,這個
r
裏面包含了
lastNonConfigurationInstances
,當activty切換的時候,系統進程經過binder機制通知app進程的client對象也就是activityThread間接調用
preExecute
方法,進行保存,而後當重建activity的時候再系統進程經過binder機制通知app進程的client對象也就是activityThread(由activityThread.h發送
H.RELAUNCH_ACTIVITY
消息經過handler機制)間接調用
execute
方法 下圖是activity重建時候調用
execute
函數調用棧截圖
重建activty後進行attach把上個被殺死的activity存下來的
r
中
lastNonConfigurationInstances
再設置給新activity
中間省略的步驟雖然多,可是根據斷點列表走下來其實很清楚的。ide
對於如何調試app進程和系統進程,www.imooc.com/article/219… 一文中有具體操做,可是涉及到binder
類是如何進行transact
發消息給別的進程以及如何execTransact
處理別的進程消息 的c++層的原理並無給出解答,這裏推薦一篇博客 blog.csdn.net/innost/arti… 講解的還算不錯。函數