iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 6
0
自我挑戰組

學習 Android Kotlin 隨筆系列 第 6

[ Day 6 ] 探討 Fragment 從年少輕狂,到老年退休生活!(一)旋轉跳躍,我跌一圈

  • 分享至 

  • xImage
  •  

| 生命週期

  • 旋轉跳躍

  • 還正在想

| 生命週期概念

在寫 app 的時候,生命週期是一件很重要的事情!
什麼是生命週期呢?簡單來講就是一個 app 的生老病死。有可能在用這個 app 用到一半的時候,突然想去滑個 FB,或是想去打個電話,這時候會離開這個 app 而跳到其他地方,在生命週期裡就是該 app 會被 onDestroy() 掉,等到再次執行時,會再 onCreate() 出來!當然啦~在這個例子只提到了 2 個狀態,真正的生命週期可是相當複雜的呢~

相當建議想要認識這部分的朋友,去對每個階段都 override 出來,並且把他們印出來(Log.d()),去觀察每個階段的先後順序,會更有概念唷!

相較於掌握自己人生不可預知的週期,掌握 android 的 app 相對容易許多

  • 沒處理生命週期

    • 由上述發現,奇怪,怎麼旋轉個螢幕回來,一切都不一樣了QQ原本的資料都被清掉了?在旋轉螢幕的時候,整個 app 會把 Activity 給清掉,並且產生一個橫向新的 Activity,跟我們原先以為單純的旋轉可不一樣呢!而在探討生命週期,又會區分 Activity 的或者是 Fragement 的,可以參考下圖唷!

  • FragmentActivity 生命週期圖

    • 上圖可以看到,相較於 ActivityFragment 的人生階段分得更為精細,而這張對比圖則是大致上去相互呼應兩者相同的階段。

  • 小筆記

    • 因為這邊有太多細項能夠討論的,兩者的大致流程不外乎從出生 onCreate() 到呈現畫面的 running 狀態,如果有要離開目前的畫面,則有可能進入臨死之前的遺言狀態(我自己為了好記亂取的...) onSaveInstance(),這邊可以在被 onDestroy() 之前,把該存好的存好,把該交代好的都先說好,然後離開QQ當下次回來時,會去檢查是否有曾經遺留保存下來的 Bundle 資料 (savedInstanceState),並且對他做使用唷!這邊的 "回來",或是 "重生",的意思又有分做 onResumeonCreateView 的不同階段,端看你怎麼死去的(可以從圖上清楚看出對應的關係)

| 實作概念

  • 建立界面

    這邊我建立了一個 EditTextTextView 以及一個 ImageButton,為的是在 EditText 輸入字串之後,按下 ImageButton ==字串會顯示在 TextView==,接著我做旋轉螢幕的動作,如果沒有特別在生命週期的階段做處理,會因為 onDestroy() 的關係,==TextView 的字串會消失==

  • 臨走前,交代 onSaveInstanceState()

    現在我們都知道了,在 onDestroy() 之後,所有原本的資料都會被清空,但我希望我再次回來時,資料還能保存起來,該怎辦?在翻轉手機,準備進入 onDestroy() 之前,會先進入 onSaveInstanceState() 階段,我們必須把要保存的資料,先塞進去一個叫做 outStateBundle 裡面,確定塞好之後,就可以安心的去了。這邊需要對這比資料加入一個 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 的,但是怎麼實際運用也沒多研究就是了


上一篇
[ Day 5 ] 上線~Android 新手登入囉!(番外篇)快速建立 Express server 來幫我寫作業
下一篇
[ Day 7 ] 探討 Fragment 從年少輕狂,到老年退休生活!(二)忍術 切頁之術!
系列文
學習 Android Kotlin 隨筆30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言