編輯:關於Android編程
背景:之前有過兩篇寫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的地方進行如下的配置
android:screenOrientation=portrait android:screenOrientation=landscape或者在onCreate裡面
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); or setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
這樣就可以保證是豎屏總是豎屏了,或者橫屏總是橫屏。
以上,就不涉及狀態保存和布局適應了,不管橫屏豎屏一切如初。
一、JNI概述 JNI 是Java Native Interface的縮寫,中文翻譯為“Java本地調用”,JNI 是本地編程接口。它使得在 Java 虛擬機 (VM)
Android學習篇:Activity介紹:Activity是Android系統提供的一個活動基類,它是一種可以包含用戶界面的組件,我們項目中所有的活動都必須繼承它才擁有
第一次見到ViewPager這個控件,瞬間愛不釋手,做東西的主界面通通ViewPager,以及圖片切換也拋棄了ImageSwitch之類的,開始讓ViewPager來做。
Android Studio快速提取方法 在開發過程中,有時在一個方法內部寫了過多的代碼,然後想要把一些代碼提取出來封裝下,分離開放在一個單獨的方法裡,可能你的