標籤:
背景:之前有過兩篇寫activity的部落格
android之activity的生命週期詳解:詳細介紹了activity的整個生命週期、各狀態間的轉換和返回案頭時儲存activity的狀態
android之activity中onSaveInstanceState和onRestoreInstanceState的觸發時機:介紹了activity中這兩個方法的觸發時機和作用
本篇部落格會牽扯到裡面的內容,如果你都有所瞭解可以直接往下看,如果不瞭解可以進去回憶下。
問題:在做應用的退出對話方塊時,發現如果對話方塊彈出,然後把手機橫豎屏切換一下,對話方塊就消失了。知道activity在橫豎屏切換時會走一些生命週期,就誤以為是在onPause和onResume的時候沒有把對話方塊恢複出來,
首先想到就是設一個全域變數isDialogShow用來儲存對話方塊是否顯示,在onPause中檢查下如果顯示了,就把isDialogShow設定為true,然後在onResume中判斷下isDialogShow的值,如果為true,則把對話方塊在顯示出來。
以為這樣就解決了,運行發現不對,對話方塊還是不顯示。
然後debug發現,每次進入onResume的時候,isDialogShow都是false,也就是說每次isDialogShow都被重新初始化了。
這時候才突然意識到,橫豎屏切換的時候生命週期可能不是我想的那樣。
就藉著這個機會去總結一下activity橫豎屏切換時如何儲存狀態以及調適型配置。
解決方案:對於這個問題,有三種方案
1??順應activity的生命週期,儲存然後恢複狀態,onCreate中動態適應布局。
2??在AndroidManifest.xml中設定,不讓activity重走生命週期從而儲存狀態,然後通過onConfigurationChanged調適型配置
3??禁止activity的橫豎屏轉換,狀態和布局保持原樣。
方案一:
首先把activity的每個方法列印出來。
啟動應用(此時是豎屏):
切換為橫屏:
裡面的數字是加的一個全域變數(初始化為0,每進入一次onPause自動加1),用來看數值的變化,可見在onPause的時候還是1,等切換完成再回來的時候就成了0了。
也很容易理解,activity相當於完全重新做了一次初始化,完整走了一遍生命週期。
同時也注意到,切換為橫屏的時候多了onSaveInstanceState和onRestoreInstanceState方法,上面第二篇部落格裡面說到的,activity在有“被銷毀的可能”時,就會調用onSaveInstanceState方法,給你一個機會去儲存activity中的資料,之後橫豎屏切換時activity確實在“未經你許可的情況下被銷毀了”,所以系統又會調用onRestoreInstanceState方法,讓你把之前儲存的資料恢複。
所以這樣就明白了為什麼我的對話方塊切換橫豎屏之後不出來,而且用來記錄的isDialogShow的值會被重設,如此解決方案也有了。
在onSaveInstanceState方法中儲存isDialogShow的值,然後在onRestoreInstanceState方法中取回isDialogShow 的值,去判斷該不該顯示對話方塊就可以了。
那麼如何調適型配置呢,像xml之類的資源,只要建兩套就可以了,橫屏資源放在res/layout-land裡面,豎屏資源放在res/layout-port檔案夾裡面,資源名字都一樣即可,系統會自己去找。
也可以通過以下方法擷取目前橫豎屏狀態分別實現一些資源的載入。
if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { //do something} else if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { //do something}
以上就完成了在activity的完整生命週期裡面儲存狀態以及自適應資源。
方案二:
在說方案二的時候要提一下,既然可以避免activity重新走生命週期,為什麼還要設計這個橫豎屏切換的時候去完整的重新走一遍生命週期呢?
因為既然手機切換了橫豎屏,比如從豎屏切換為橫屏了,那麼原來豎屏的layout,drawable等資源可能無法適應橫屏模式,設計完善的應用一般是會有兩套資源來適配橫豎屏模式的,所以在切換後重啟activity,在新的建立過程中就會自
動使用橫屏的資源,實現了動態適應。
方案二隻需要在manifest檔案中的activity標籤下加如下代碼
android:configChanges="orientation"
這段代碼的含義是向系統說明,這個activity的orientation發生變化時,我不需要你去自適應,我自己會在onConfigurationChanged方法中做處理,我自己完成橫豎屏切換的適應,即告訴activity不要重新走生命週期,放著我來。
加上這個代碼聲明之後,重新運行會發現,activity的生命週期沒有出現,只出現了一個方法就是
那麼切換過程中你要如何處理就是你自己的事情了,狀態無需儲存,都還是原來的,如果要做一些切換的話,可以通過如下代碼擷取到當前的橫豎屏狀態,然後自己操作。
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) { // do something} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) { // do something}
如果只是加下面這個的話,你會發現activity還是會走完整的生命週期,onConfigurationChanged方法壓根不會執行
android:configChanges="orientation"
這是因為從Android 3.2(API 13)開始,橫豎屏切換時不僅orientation會發生變化,screenSize也會跟著發生變化,所以要改成下面這樣。android:configChanges="orientation|screenSize"告訴activity,不管是orientation變化還是screenSize變化,都不要重新初始化,都通過onConfigurationChanged讓我自己操作。
以上就是不讓activity重新初始化,而是自己完成橫豎屏切換的自適應操作。
方案三:
最簡單最粗暴,禁止橫豎屏轉換,直接固定為橫屏或者豎屏。
可以在配置Activity的地方進行如下的配置
android:screenOrientation="portrait"android:screenOrientation="landscape"
或者在onCreate裡面
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);orsetRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
這樣就可以保證是豎屏總是豎屏了,或者橫屏總是橫屏。
以上,就不涉及狀態儲存和布局適應了,不管橫屏豎屏一切如初。
參考:
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2012/1106/516.html
http://blog.csdn.net/aliang775/article/details/8561075
jason0539
微博:http://weibo.com/2553717707
部落格:http://blog.csdn.net/jason0539(轉載請說明出處)
android開發之activity橫豎屏切換時的生命週期以及橫豎屏切換時的資源適配方案