Android零基礎(chǔ)入門(mén)第76節(jié):Activity數(shù)據(jù)保存和橫豎屏切換

在前面幾期學(xué)習(xí)了Activity的創(chuàng)建、配置、啟動(dòng)和停止,還學(xué)了Activity的生命周期,本期一起來(lái)學(xué)習(xí)Activity有關(guān)的更多事兒。

一、數(shù)據(jù)保存

通過(guò)上一期 LogCat 窗口打印的日志可以看出,當(dāng) Activity失去焦點(diǎn)時(shí),首先必然會(huì)執(zhí)行onPause()方法,因此當(dāng)項(xiàng)目中需要保存數(shù)據(jù)時(shí),可以在onPause()方法中保存。同時(shí),當(dāng)兩個(gè)Activity跳轉(zhuǎn)時(shí), MainActivity會(huì)先失去焦點(diǎn)讓SecondActivity得到焦點(diǎn),等到SecondActivity完全顯示在前臺(tái)時(shí)MainActivity才會(huì)切換到后臺(tái)。

可能有的同學(xué)已經(jīng)發(fā)現(xiàn),在 Activity的生命周期方法中,只有第一個(gè) onCreate()回調(diào)方法帶有參數(shù) savedInstanceState,其他回調(diào)方法都是沒(méi)有參數(shù)的,這個(gè)參數(shù)有什么作用呢?

經(jīng)常會(huì)出現(xiàn)用戶(hù)按到 HOME鍵退出了界面,或者安卓系統(tǒng)意外回收了應(yīng)用,這種情況下,使用 savedInstanceState就可以讓用戶(hù)再次打開(kāi)應(yīng)用時(shí)恢復(fù)原來(lái)的狀態(tài)。

在具體學(xué)習(xí)savedInstanceState之前,先來(lái)了解一下onSaveInstanceState() 和 onRestoreInstanceState() 方法,這兩個(gè)方法并不是Activity的生命周期方法,它們不同于 onCreate()、onPause()等生命周期方法,它們并不一定會(huì)被回調(diào)。當(dāng)應(yīng)用遇到意外情況(如:內(nèi)存不足、用戶(hù)直接按HOME鍵)由系統(tǒng)銷(xiāo)毀一個(gè)Activity時(shí),onSaveInstanceState() 會(huì)被調(diào)用;但是當(dāng)用戶(hù)主動(dòng)去銷(xiāo)毀一個(gè)Activity時(shí)(如在應(yīng)用中按返回鍵),onSaveInstanceState()就不會(huì)被調(diào)用。因?yàn)樵谶@種情況下,用戶(hù)的行為決定了不需要保存Activity的狀態(tài)。通常onSaveInstanceState()只適合用于保存一些臨時(shí)性的狀態(tài),而onPause()適合用于數(shù)據(jù)的持久化保存。

在Activity被殺掉之前調(diào)用保存每個(gè)實(shí)例的狀態(tài),以保證該狀態(tài)可以在onCreate(Bundle)或者onRestoreInstanceState(Bundle) (傳入的Bundle參數(shù)是由onSaveInstanceState封裝好的)中恢復(fù)。這個(gè)方法在一個(gè)Activity被殺死前調(diào)用,當(dāng)該Activity在將來(lái)某個(gè)時(shí)刻回來(lái)時(shí)可以恢復(fù)其先前狀態(tài)。 例如,如果Activity B啟用后位于Activity A的前端,在某個(gè)時(shí)刻Activity A因?yàn)橄到y(tǒng)回收資源的問(wèn)題要被殺掉,A通過(guò)onSaveInstanceState將有機(jī)會(huì)保存其用戶(hù)界面狀態(tài),使得將來(lái)用戶(hù)返回到Activity A時(shí)能通過(guò)onCreate(Bundle)或者onRestoreInstanceState(Bundle)恢復(fù)界面的狀態(tài)。

onSaveInstanceState()方法會(huì)在什么時(shí)候被執(zhí)行,有這么幾種情況:

當(dāng)用戶(hù)按下HOME鍵時(shí)。

長(zhǎng)按HOME鍵,選擇運(yùn)行其他的程序時(shí)。

按下電源按鍵(關(guān)閉屏幕顯示)時(shí)。

從Activity A中啟動(dòng)一個(gè)新的Activity時(shí)。

屏幕方向切換時(shí),例如從豎屏切換到橫屏?xí)r。

總而言之,onSaveInstanceState()的調(diào)用遵循一個(gè)重要原則,即當(dāng)系統(tǒng)存在“未經(jīng)你許可”時(shí)銷(xiāo)毀了我們的Activity的可能時(shí),則onSaveInstanceState()會(huì)被系統(tǒng)調(diào)用,這是系統(tǒng)的責(zé)任,因?yàn)樗仨氁峁┮粋€(gè)機(jī)會(huì)讓你保存你的數(shù)據(jù)。

onRestoreInstanceState()方法一般是在onStart()和onResume()之間執(zhí)行。其被調(diào)用的前提是,Activity A確實(shí)被系統(tǒng)銷(xiāo)毀了,而如果僅僅是停留在有這種可能性的情況下,則該方法不會(huì)被調(diào)用,例如,當(dāng)正在顯示Activity A的時(shí)候,用戶(hù)按下HOME鍵回到主界面,然后用戶(hù)緊接著又返回到Activity A,這種情況下Activity A一般不會(huì)因?yàn)閮?nèi)存的原因被系統(tǒng)銷(xiāo)毀,故Activity A的onRestoreInstanceState方法不會(huì)被執(zhí)行。此也說(shuō)明上二者,大多數(shù)情況下不成對(duì)被使用。

二、橫豎屏切換

關(guān)于橫豎屏切換,這一塊其實(shí)有很多事情,接下來(lái)一一進(jìn)行學(xué)習(xí)。

1、可以橫豎屏切換但禁止銷(xiāo)毀重建

現(xiàn)實(shí)生活中,使用手機(jī)時(shí)會(huì)根據(jù)不同情洗進(jìn)行橫豎屏切換。當(dāng)手機(jī)橫豎屏切換時(shí),Activity會(huì)銷(xiāo)毀重建。

這里使用上一期Activity生命周期的示例,當(dāng)程序運(yùn)行時(shí),這時(shí)候切換模擬器或手機(jī)的橫豎屏方向,可以在LogCat 窗口看到下圖所示的輸出:

從上圖可以看出,當(dāng)橫豎屏切換時(shí)Activity會(huì)依次回調(diào)onPause()、onStop()、 onDestory()、onCreate()、onStar()、onResume()方法。這種情況對(duì)實(shí)際開(kāi)發(fā)肯定會(huì)有影響,那應(yīng)該如何解決呢?

如果不希望在橫豎屏切換時(shí)Activity被銷(xiāo)毀重建,可以在 AndroidManifest.xml文件中設(shè)置 Activity的android:conflgChanges的屬性,這樣無(wú)論怎樣切換Activity都不會(huì)銷(xiāo)毀重新創(chuàng)建,具體設(shè)置代碼如下所示:

android:configChanges="orientation丨keyboardHidden丨screenSize"

2、禁止橫豎屏切換

如果希望某一個(gè)界面一直處于豎豎橫屏狀態(tài),不隨手機(jī)的晃動(dòng)而改變,同樣可以在清單文件中通過(guò)設(shè)置Activity的android:screenOrientation屬性來(lái)完成。該屬性主要有以下幾個(gè)值:

unspecified:默認(rèn)值由系統(tǒng)來(lái)判斷顯示方向。判定的策略是和設(shè)備相關(guān)的,不同的設(shè)備會(huì)有不同的顯示方向。

landscape:橫屏顯示(寬比高要長(zhǎng))。

portrait:豎屏顯示(高比寬要長(zhǎng))。

user:用戶(hù)當(dāng)前首選的方向。

behind:和該Activity下面的那個(gè)Activity的方向一致(在Activity堆棧中的)。

sensor:有物理的感應(yīng)器來(lái)決定。如果用戶(hù)旋轉(zhuǎn)設(shè)備這屏幕會(huì)橫豎屏切換。

nosensor:忽略物理感應(yīng)器,這樣就不會(huì)隨著用戶(hù)旋轉(zhuǎn)設(shè)備而更改了("unspecified"設(shè)置除外)。

比如設(shè)置為豎屏并不可切換方向,具體設(shè)置代碼如下所示:

android:screenOrieritation="portrait"

除了在配置文件中配置,其實(shí)還可以在Java文件中設(shè)置,只要在onCreate方法中加一句代碼即可,如保持豎屏代碼為:

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

如保持橫屏,代碼為:

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

當(dāng)然在實(shí)際開(kāi)發(fā)中不可能每個(gè)Activity都這樣多加一句,不僅維護(hù)麻煩而且容易出錯(cuò)。一般都是先定義一個(gè)BaseActivity,讓其繼承Activity,然后重寫(xiě)onCreate方法,并進(jìn)行橫豎屏設(shè)置,最后讓其他的Activity繼承BaseActivity即可。

3、橫豎屏切換同時(shí)切換不同布局

在開(kāi)發(fā)中有時(shí)候希望橫豎屏?xí)r加載不同的布局,可以通過(guò)兩種方式來(lái)實(shí)現(xiàn):

準(zhǔn)備兩套不同的布局,Android會(huì)自己根據(jù)橫豎屏加載不同布局。layout-land為橫屏,layout-port為豎屏。然后把這兩套布局文件放這兩文件夾里,文件名一樣,Android就會(huì)自行判斷加載相應(yīng)布局。

在Java代碼中進(jìn)行判斷,自己想加載什么就加載什么。一般是在onCreate()方法中加載布局文件,可以對(duì)橫豎屏的狀態(tài)做下判斷,關(guān)鍵代碼如下:

if(this.getResources().getConfiguration().orientation==Configuration.ORIENTATION_LANDSCAPE){

setContentView(R.layout.橫屏布局);

}elseif(this.getResources().getConfiguration().orientation==Configuration.ORIENTATION_PORTRAIT){

setContentView(R.layout.豎屏布局);

}

當(dāng)然在橫豎屏切換過(guò)程中,可以讓Activity銷(xiāo)毀重建,需要注意的就是相關(guān)數(shù)據(jù)的保存,可以參考前面數(shù)據(jù)保存部分的內(nèi)容,當(dāng)然還可以通過(guò)其他方式來(lái)完成,如數(shù)據(jù)持久化,后期再逐步來(lái)學(xué)習(xí)。


今天就先到這里,如果有問(wèn)題歡迎留言一起探討,也歡迎加入Android零基礎(chǔ)入門(mén)技術(shù)討論微信群,共同成長(zhǎng)!

如果該系列分享對(duì)你有幫助,就動(dòng)動(dòng)手指關(guān)注、點(diǎn)贊、留言吧,你的互動(dòng)就是對(duì)我最大的鼓勵(lì)!

此文章版權(quán)為微信公眾號(hào)分享達(dá)人秀(ShareExpert)——鑫鱻所有,若需轉(zhuǎn)載請(qǐng)聯(lián)系作者授權(quán),特此聲明!

往期總結(jié)回顧:

Android零基礎(chǔ)入門(mén)第1節(jié):Android的前世今生

Android零基礎(chǔ)入門(mén)第2節(jié):Android 系統(tǒng)架構(gòu)和應(yīng)用組件那些事

Android零基礎(chǔ)入門(mén)第3節(jié):帶你一起來(lái)聊一聊Android開(kāi)發(fā)環(huán)境

Android零基礎(chǔ)入門(mén)第4節(jié):正確安裝和配置JDK, 高富帥養(yǎng)成第一招

Android零基礎(chǔ)入門(mén)第5節(jié):善用ADT Bundle, 輕松邂逅女神

Android零基礎(chǔ)入門(mén)第6節(jié):配置優(yōu)化SDK Manager, 正式約會(huì)女神

Android零基礎(chǔ)入門(mén)第7節(jié):搞定Android模擬器,開(kāi)啟甜蜜之旅

Android零基礎(chǔ)入門(mén)第8節(jié):HelloWorld,我的第一趟旅程出發(fā)點(diǎn)

Android零基礎(chǔ)入門(mén)第9節(jié):Android應(yīng)用實(shí)戰(zhàn),不懂代碼也可以開(kāi)發(fā)

Android零基礎(chǔ)入門(mén)第10節(jié):開(kāi)發(fā)IDE大升級(jí),終于迎來(lái)了Android Studio

Android零基礎(chǔ)入門(mén)第11節(jié):簡(jiǎn)單幾步帶你飛,運(yùn)行Android Studio工程

Android零基礎(chǔ)入門(mén)第12節(jié):熟悉Android Studio界面,開(kāi)始裝逼賣(mài)萌

Android零基礎(chǔ)入門(mén)第13節(jié):Android Studio個(gè)性化配置,打造開(kāi)發(fā)利器

Android零基礎(chǔ)入門(mén)第14節(jié):使用高速Genymotion,跨入火箭時(shí)代

Android零基礎(chǔ)入門(mén)第15節(jié):掌握Android Studio項(xiàng)目結(jié)構(gòu),揚(yáng)帆起航

Android零基礎(chǔ)入門(mén)第16節(jié):Android用戶(hù)界面開(kāi)發(fā)概述

Android零基礎(chǔ)入門(mén)第17節(jié):文本框TextView

Android零基礎(chǔ)入門(mén)第18節(jié):輸入框EditText

Android零基礎(chǔ)入門(mén)第19節(jié):按鈕Button

Android零基礎(chǔ)入門(mén)第20節(jié):復(fù)選框CheckBox和單選按鈕RadioButton

Android零基礎(chǔ)入門(mén)第21節(jié):開(kāi)關(guān)組件ToggleButton和Switch

Android零基礎(chǔ)入門(mén)第22節(jié):圖像視圖ImageView

Android零基礎(chǔ)入門(mén)第23節(jié):圖像按鈕ImageButton和縮放按鈕ZoomButton

Android零基礎(chǔ)入門(mén)第24節(jié):自定義View簡(jiǎn)單使用,打造屬于你的控件

Android零基礎(chǔ)入門(mén)第25節(jié):簡(jiǎn)單且最常用的LinearLayout線性布局

Android零基礎(chǔ)入門(mén)第26節(jié):兩種對(duì)齊方式,layout_gravity和gravity大不同

Android零基礎(chǔ)入門(mén)第27節(jié):正確使用padding和margin

Android零基礎(chǔ)入門(mén)第28節(jié):輕松掌握RelativeLayout相對(duì)布局

Android零基礎(chǔ)入門(mén)第29節(jié):善用TableLayout表格布局

Android零基礎(chǔ)入門(mén)第30節(jié):兩分鐘掌握FrameLayout幀布局

Android零基礎(chǔ)入門(mén)第31節(jié):少用的AbsoluteLayout絕對(duì)布局

Android零基礎(chǔ)入門(mén)第32節(jié):新推出的GridLayout網(wǎng)格布局

Android零基礎(chǔ)入門(mén)第33節(jié):Android事件處理概述

Android零基礎(chǔ)入門(mén)第34節(jié):Android中基于監(jiān)聽(tīng)的事件處理

Android零基礎(chǔ)入門(mén)第35節(jié):Android中基于回調(diào)的事件處理

Android零基礎(chǔ)入門(mén)第36節(jié):Android系統(tǒng)事件的處理

Android零基礎(chǔ)入門(mén)第37節(jié):初識(shí)ListView

Android零基礎(chǔ)入門(mén)第38節(jié):初識(shí)Adapter

Android零基礎(chǔ)入門(mén)第39節(jié):ListActivity和自定義列表項(xiàng)

Android零基礎(chǔ)入門(mén)第40節(jié):自定義ArrayAdapter

Android零基礎(chǔ)入門(mén)第41節(jié):使用SimpleAdapter

Android零基礎(chǔ)入門(mén)第42節(jié):自定義BaseAdapter

Android零基礎(chǔ)入門(mén)第43節(jié):ListView優(yōu)化和列表首尾使用

Android零基礎(chǔ)入門(mén)第44節(jié):ListView數(shù)據(jù)動(dòng)態(tài)更新

Android零基礎(chǔ)入門(mén)第45節(jié):網(wǎng)格視圖GridView

Android零基礎(chǔ)入門(mén)第46節(jié):列表選項(xiàng)框Spinner

Android零基礎(chǔ)入門(mén)第47節(jié):自動(dòng)完成文本框AutoCompleteTextView

Android零基礎(chǔ)入門(mén)第48節(jié):可折疊列表ExpandableListView

Android零基礎(chǔ)入門(mén)第49節(jié):AdapterViewFlipper圖片輪播

Android零基礎(chǔ)入門(mén)第50節(jié):StackView卡片堆疊

Android零基礎(chǔ)入門(mén)第51節(jié):進(jìn)度條ProgressBar

Android零基礎(chǔ)入門(mén)第52節(jié):自定義ProgressBar炫酷進(jìn)度條

Android零基礎(chǔ)入門(mén)第53節(jié):拖動(dòng)條SeekBar和星級(jí)評(píng)分條RatingBar

Android零基礎(chǔ)入門(mén)第54節(jié):視圖切換組件ViewSwitcher

Android零基礎(chǔ)入門(mén)第55節(jié):ImageSwitcher和TextSwitcher

Android零基礎(chǔ)入門(mén)第56節(jié):翻轉(zhuǎn)視圖ViewFlipper

Android零基礎(chǔ)入門(mén)第57節(jié):DatePicker和TimePicker選擇器

Android零基礎(chǔ)入門(mén)第58節(jié):數(shù)值選擇器NumberPicker

Android零基礎(chǔ)入門(mén)第59節(jié):常用三大Clock時(shí)鐘組件

Android零基礎(chǔ)入門(mén)第60節(jié):日歷視圖CalendarView和定時(shí)器Chronometer

Android零基礎(chǔ)入門(mén)第61節(jié):滾動(dòng)視圖ScrollView

Android零基礎(chǔ)入門(mén)第62節(jié):搜索框組件SearchView

Android零基礎(chǔ)入門(mén)第63節(jié):值得借鑒學(xué)習(xí)的選項(xiàng)卡TabHost

Android零基礎(chǔ)入門(mén)第64節(jié):揭開(kāi)RecyclerView廬山真面目

Android零基礎(chǔ)入門(mén)第65節(jié):RecyclerView分割線開(kāi)發(fā)技巧

Android零基礎(chǔ)入門(mén)第66節(jié):RecyclerView點(diǎn)擊事件處理

Android零基礎(chǔ)入門(mén)第67節(jié):RecyclerView數(shù)據(jù)動(dòng)態(tài)更新

Android零基礎(chǔ)入門(mén)第68節(jié):RecyclerView添加首尾視圖

Android零基礎(chǔ)入門(mén)第69節(jié):ViewPager快速實(shí)現(xiàn)引導(dǎo)頁(yè)

Android零基礎(chǔ)入門(mén)第70節(jié):ViewPager打造TabHost效果

Android零基礎(chǔ)入門(mén)第71節(jié):CardView簡(jiǎn)單實(shí)現(xiàn)卡片式布局

Android零基礎(chǔ)入門(mén)第72節(jié):SwipeRefreshLayout下拉刷新

Android零基礎(chǔ)入門(mén)第73節(jié):Activity創(chuàng)建和配置

Android零基礎(chǔ)入門(mén)第74節(jié):Activity啟動(dòng)和關(guān)閉

Android零基礎(chǔ)入門(mén)第75節(jié):Activity狀態(tài)和生命周期

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容