1. 程式人生 > >Android中Fragment資料儲存和恢復

Android中Fragment資料儲存和恢復

原文地址:請掃文後stormzhang大神的微信公眾號——AndroidDeveloper

寫在前面

上週我們總結了Activity中資料的儲存和恢復,我們花兩分鐘來回顧一下:


一句話總結

  • 臨時資料
    對於臨時資料,我們使用onSaveInstanceState方法進行儲存,並且在onCreate方法中恢復。

  • 永久資料
    對於永續性資料,我們要在onPause方法中進行儲存,但是要注意,onPause方法中不能進行大量操作,會影響其他Activity進入任務棧棧頂。

ps:在Activity中彈出一個當前Activity的Dialog並不會有任何生命週期方法呼叫(以前我曾以為會呼叫onPause方法)。因為Dialog作為一個View本身就是屬於當前Activity的,Activity並沒有失去焦點。

ok,完成了回顧,下面來開始本篇部落格:

Fragment在我們的專案中真的太實用和常見了,它的使用頻率和數量甚至超過了Activity,所以本文目的是探究Fragment的資料儲存和恢復。

在開始講解之前,你應該對Fragment的生命週期方法有一定了解,推薦給大家一篇部落格,我認為不錯:

準備工作做了這麼多,下面我們正式開始吧!


本文直接選用了「第一行程式碼」中Fragment模組的講解例子,點選下面的按鈕分別跳轉這四個Fragment。為了方便觀察,我重寫了Fragment所有生命週期方法和onSaveInstanceState方法,並列印了Log。

我們目的是探究Fragment資料的儲存和恢復,在這裡我把它分為兩大類的情況:

  • 1. 單個Fragment遭遇一些突發情況

  • 2. Fragment之間相互的切換或覆蓋

在此之前,先引入一個返回棧的概念。

我想你應該知道返回棧是什麼,並且你以前接觸的應該是儲存Activity的返回棧,類比Activity,Fragment返回棧其實是儲存Fragment的棧結構。區別在於:Fragment的返回棧由Activity管理;而Activity的返回棧由系統管理。

在未修改之前,本文新增並切換Fragment的方式都是在返回棧中僅有一個 fragment:


不要心急,過一會再說怎麼去在返回棧中壓入多個fragment,我們先來處理只有一個的情況

1. 單個Fragment遭遇突發情況

仍然是用以下突發情況進行測試:

  • 點選back鍵

  • 點選鎖屏鍵

  • 點選home鍵

  • 其他APP進入前臺

  • 啟動了另一個Activity

  • 螢幕方向旋轉

  • APP被Kill

不過與上篇部落格不同的是,我們在清單檔案中,給Activity做了如下配置:


這麼做的目的是當螢幕方向發生改變的時候,fragment所依附的Activity並不會重新銷燬再建立,讓情況相對簡單一點。

測試結果

當一個fragment孤零零地呆在返回棧時,它所處的情況與Activity如出一轍。類比Activity對資料的儲存和恢復,我們可以對此得出結論:

  • 臨時資料 對於臨時資料,我們使用onSaveInstanceState方法進行儲存,並且在onCreateView方法中恢復(請注意是onCreateView)。

  • 永久資料 對於永續性資料,我們要在onPause方法中進行儲存。

2. Fragment之間的相互切換或覆蓋

當返回棧中保證只有一個Fragment,相互切換時,生命週期方法的呼叫是怎樣的呢?例如本例中,從fragment03切換到fragment04:

可以看到,上述的這種情況,兩個fragment從建立到銷燬,經歷了所有的生命週期方法。

如果返回棧中fragment的數量為多個呢?首先在切換時,加上以下程式碼,保證將fragment放入返回棧中:


使用addToBackStack方法,就能將fragment放入相應的返回棧中去了,從表象上來看區別在於進入其他fragment時,點選back鍵時,可以返回上一個fragment。這時候切換時,生命週期方法就是如何呼叫的呢?

對比這兩張生命週期方法的圖,能得出兩個結論。

  • 1. 無論任務棧中fragment數量為多少,onSaveInstanceState方法都沒有呼叫

  • 2. 當fragment任務棧中有多個fragment時,進入下一個fragment時,並不會銷燬fragment例項,而是僅僅銷燬檢視,最終呼叫的方法為onDestoryView。
      

所以此時我們要去儲存臨時資料,並不能僅儲存在onSaveInstanceState中(因為它可能不會呼叫),還應該在onDestoryView方法中進行儲存臨時資料的操作,原始碼如下:


因為沒有了系統提供的bundle引數,我們選擇把資料儲存在Arguments中,程式碼就不帶著大家一步一步的看了,因為邏輯並不複雜,挺好理解的。通過這種方式,我們就挺容易的將臨時資料和fragment的一些狀態儲存進bundle中並在需要時恢復了。

不知不覺本篇文章就要結束了,感興趣的可以嘗試當呼叫ft.add()方式去新增fragment時,生命週期方法又是怎樣呼叫的呢?

一句話總結本文

Fragment對臨時資料的儲存,僅僅依靠onSaveInstanceState方法是不行的,還需要在onDestoryView中進行相應操作,具體參考上面的程式碼。

Fragment中對於一些永續性的資料,仍應在onPause中儲存。

投稿作者:MeloDev

原文:http://www.jianshu.com/p/015c79bedb41

微信不支援外鏈,可點選「閱讀原文」檢視,覺得有幫助不妨轉發支援下,長按二維碼訂閱。