旋轉跳躍
還正在想
在寫 app 的時候,生命週期是一件很重要的事情!
什麼是生命週期呢?簡單來講就是一個 app 的生老病死。有可能在用這個 app 用到一半的時候,突然想去滑個 FB,或是想去打個電話,這時候會離開這個 app 而跳到其他地方,在生命週期裡就是該 app 會被 onDestroy()
掉,等到再次執行時,會再 onCreate()
出來!當然啦~在這個例子只提到了 2 個狀態,真正的生命週期可是相當複雜的呢~
相當建議想要認識這部分的朋友,去對每個階段都 override
出來,並且把他們印出來(Log.d()
),去觀察每個階段的先後順序,會更有概念唷!
相較於掌握自己人生不可預知的週期,掌握 android 的 app 相對容易許多
沒處理生命週期
由上述發現,奇怪,怎麼旋轉個螢幕回來,一切都不一樣了QQ原本的資料都被清掉了?在旋轉螢幕的時候,整個 app 會把 Activity
給清掉,並且產生一個橫向新的 Activity
,跟我們原先以為單純的旋轉可不一樣呢!而在探討生命週期,又會區分 Activity
的或者是 Fragement
的,可以參考下圖唷!
Fragment
和 Activity
生命週期圖
上圖可以看到,相較於 Activity
,Fragment
的人生階段分得更為精細,而這張對比圖則是大致上去相互呼應兩者相同的階段。
小筆記
onCreate()
到呈現畫面的 running 狀態,如果有要離開目前的畫面,則有可能進入臨死之前的遺言狀態(我自己為了好記亂取的...) onSaveInstance()
,這邊可以在被 onDestroy()
之前,把該存好的存好,把該交代好的都先說好,然後離開QQ當下次回來時,會去檢查是否有曾經遺留保存下來的 Bundle
資料 (savedInstanceState
),並且對他做使用唷!這邊的 "回來",或是 "重生",的意思又有分做 onResume
、 onCreateView
的不同階段,端看你怎麼死去的(可以從圖上清楚看出對應的關係)建立界面
這邊我建立了一個 EditText
、TextView
以及一個 ImageButton
,為的是在 EditText
輸入字串之後,按下 ImageButton
==字串會顯示在 TextView
==,接著我做旋轉螢幕的動作,如果沒有特別在生命週期的階段做處理,會因為 onDestroy()
的關係,==TextView
的字串會消失==
臨走前,交代 onSaveInstanceState()
現在我們都知道了,在 onDestroy()
之後,所有原本的資料都會被清空,但我希望我再次回來時,資料還能保存起來,該怎辦?在翻轉手機,準備進入 onDestroy()
之前,會先進入 onSaveInstanceState()
階段,我們必須把要保存的資料,先塞進去一個叫做 outState
的 Bundle
裡面,確定塞好之後,就可以安心的去了。這邊需要對這比資料加入一個 key
值,之後如果要再取出資料,就必須靠這筆 key
值才找得回來唷
override fun onSaveInstanceState(outState: Bundle) {
Log.d("state", "onSaveInstanceState")
outState.putString(SPIN_KEY, show_input?.text.toString())
super.onSaveInstanceState(outState)
}
甦醒!怎麼取之前保存好的值呢?
在這邊我們使用了 onActivityCreated()
,當他的參數 savedInstanceState()
有原先指定的 key
值,表示找得到資料,如果是空的(譬如第一次開啟這個 app),那就沒資料而不做任何動作。在 onCreateView()
之後會進到這個階段,如果有取到 key
值的話,就可以把這個值給送回去給原本的主人(在這邊是 TextView
),一切就像是一直都沒離開過囉!
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
Log.d("state", "onActivityCreated")
val spinValue = savedInstanceState?.getString(SPIN_KEY)
if(spinValue != null){
show_input.text = spinValue
Log.d("restore data", spinValue)
}
}
不會進 onSaveInstance()
?
在旋轉螢幕的時候,都會經過 onSaveInstance()
,但是在實驗切換 Fragment
時,怎麼跟想像的不一樣呢?後來才之後,onSaveInstance()
只有在 Activity
發生要 onDestroy
時才有作用,而這邊的是 Fragment
要離開了,但是原先的 Activity
還活得好好的,當然不會進去囉
onSaveInstance()
不會存值?
這個坑是之前卡蠻久的,後來才知道自己 override
到另一個 function,叫做 onSaveInstanceState(outState: Bundle?, outPersistentState: PersistableBundle?)
。這個是給 app.Activity
用的,而自己卻是 app.AppCompatActivity
,所以應該用的是 onSaveInstanceState(outState: Bundle?)
才對喲!後來查了一下,PersistableBundle
似乎是用在當 reboot 之後要去拿取 data 的,但是怎麼實際運用也沒多研究就是了