編輯:關於android開發
我們知道,當Configuration Change發生的時候(比如橫豎屏切換等),會導致Activity重啟,即先destroy,然後會restart,一般情況下restart的時間比較短,為了保證一致的用戶體驗,我們應該在Activity重啟前將一些數據存儲下來,然後在restart的時候重新根據這些數據更新UI。當然你可能想將這些數據寫到物理文件或數據庫中,但是這樣有缺點,因為IO操作時耗時操作,會影響restart的過程,甚至導致ANR程序無響應,本文將介紹幾種將數據緩存在內存中以便restart時進行恢復的方法。
Activity具有onSaveInstanceState回調方法,如果onSaveInstanceState方法被調用了,那麼該回調方法一定是在onStop之前被調用的,但是不能保證是在onPause之前還是之後被調用。一般在此處將UI持久化的一些信息存入到Bundle中,然後在Activity重新創建執行onCreate(Bundle)或onRestoreInstanceState(Bundle)的時候再根據Bundle恢復。Activity.onSaveInstanceState的默認實現是遍歷層級結構中的所有含有id屬性的View,然後依次調用View.onSaveInstanceState()方法。onSaveInstanceState是android.view.View的方法,所以所有繼承自View的widget都有該方法。View.onSaveInstanceState()會存儲View自身的一些信息,比如存儲當前選擇的哪個item等。
由於Activity.onSaveInstanceState方法只會遍歷Activity中含有id屬性的View對其UI信息進行存儲,所以我們我們在編碼時最好給View都添加id屬性,這樣可以使其在上述方法執行的時候調用View的onSaveInstanceState方法,從而存儲該View的UI信息。
如果要重寫onSaveInstanceState方法,首先要調用super.onSaveInstanceState(bundle)。重寫的時候不應該在此處存儲持久化的數據(比如要向SQLite數據中寫入持久數據),應該在該方法中只存儲一些與UI相關的瞬時變量,比如有時候某些成員變量也存儲著一些和UI相關的信息,這時候就可以在onSaveInstanceState中存儲下來。
Bundle不是為存儲大量數據(比如bitmap)而設計的,並且Bundle中的數據必須經過序列化與反序列化, 因此在onSaveInstanceState不應該存儲大量數據。
onSaveInstanceState是在Activity將要被killed並且預測過段時間會重新create這樣條件下才會被調用。也就是說onSaveInstanceState之所以被調用是為了Activity在銷毀後進行重新生成進行restore的,如果Android Framework認為不滿足需要進行onSaveInstanceState的條件,那麼就不會調用該方法,具體來說:
如果用戶顯式地通過back鍵退出了程序,那麼不會調用onSaveInstanceState方法。
如果開始打開了Activity A,然後打開了Activity B,對A進行了部分遮罩,這時候會觸發A的onPause方法,但是Framework可能會避免調用A的onSaveInstanceState方法(如果在B的生命周期內A沒有被kill掉)。
由於onSaveInstanceState不適合存儲大量的數據,所以如果在Activity銷毀重建恢復數據的時候就不能使用該onSaveInstanceState毀掉函數存取大量數據了。
由於configuration change導致Activity銷毀的時候,Activity中標記為保留的Fragment不會銷毀,所以可以利用該特性實現存取數據,具體方法如下:
擴展Fragment類,並定義好相應字段存取數據,對外暴露出設置數據和獲取數據的方法,比如setData和getData
在Fragment的onCreate方法中調用方法setRetainInstance(true),標記該Fragment為保留的
將該Fragment加入到Activity中
在Activity的onDestroy方法中將activity的中需要保存的數據調用Fragment中上述定義的setData方法,將其保存在Fragment中
在Activity銷毀重新生成執行onCreate的時候,重新從Fragmet中調用getData獲取之前保存的數據
最後需要注意內存洩露的發生
Android中可以用Loader和LoaderManager異步獲取數據,且Loader機制有個很好的特性:可以在Activity執行restart的過程中繼續持有數據,也就是說,如果Loader一開始就已經加載了數據,那麼在Activity進行了restart之後,Activity會從Loader中立即獲取到之前緩存的數據,而無需再次用LoaderManager加載數據,這樣就能實現restart之後數據恢復的功能。
如果對Loader機制不了解,可以參見以下兩篇博文:
Android中Loader及LoaderManager的使用(附源碼下載)
深入源碼解析Android中Loader、AsyncTaskLoader、CursorLoader、LoaderManager
我們知道Java中如果一個類的成員變量是static的,那麼該static成員變量的生命周期就與該類的生命周期相同,具體來說:當Java虛擬機加載該類的時候,就會給該類的static成員變量分配內存空間;當Java虛擬機卸載該類的時候,該類的static成員變量的內存才會被回收。Android也具有該特性,假設我們的Activity中有一個static的成員變量,在Activity進行restart的過程中,Java虛擬機沒有卸載掉該Activity,因為在後面的restart的過程中會用到,所以在restart過程中,該Activity的static的成員變量的內存沒有被回收,這樣我們就可以在restart之前往該Activity的static成員變量中寫入值,在restart之後從Activity的static成員變量中讀取值,這樣就跨restart過程持有了數據。使用該特性也要注意,在非restart導致的destroy的時候,我們需要將Activity的static成員變量賦值為null,防止內存洩露。
Gradle混淆+打包Jar包基礎,gradle混淆打包jar本文為原創文章,轉載請注明出處。 文章最後會附帶源碼下載地址,有需要的朋友可下載。 通常我們編
淺談Android 通過ADB Wireless無線調試應用 使用數據線調試應用難免不方便,本篇博客介紹使用ADB Wireless工具,當手機和電腦處在同一網絡下,實現
算法—符號表,算法符號定義:符號表是一種存儲鍵值對的數據結構,支持兩種操作:插入(put),即將一組新的鍵值對存入表中;查找(get),即根據給定的鍵得到相應的值。 1
Android項目從Eclipse增加支持Android Studio 使用Eclipse開發Android已經有些年頭了,然而Android Studio(後面簡稱
簡單登錄案例(SharedPreferences存儲賬戶信息)&