android activity 实际,Android学习感悟之Activity
Android學(xué)習(xí)感悟之Activity,包含生命周期、啟動(dòng)模式以及一些Activity中常用的方法。
序
在Android開(kāi)發(fā)中,用的最為平凡的,最不能少的就是Activity了,所以作為學(xué)習(xí)感悟的第一篇我覺(jué)得再適合不過(guò)了。還記得剛接觸Android的時(shí)候,第一件事就是找到Hello World是怎么顯示到手機(jī)上的,那就是我第一次接觸到Activity。話不多說(shuō),直接進(jìn)入正題。
Activity的生命周期
Activity,我們常常把它譯為活動(dòng),大家都知道任何一件事都有他的流程,而在Android中把他叫做生命周期,一件事的流程無(wú)外乎都會(huì)包含,開(kāi)始,經(jīng)過(guò),結(jié)束,而在Android中Activity同樣有這些過(guò)程,只不過(guò)在程序中是由系統(tǒng)去回調(diào)這些步驟的,下邊我們可以先看一下,這些過(guò)程有哪些。
來(lái)自于Android developer training:
basic-lifecycle.png
可以看到依次包含:onCreate()->onStart()->onResume()->onPaused()->onStop()->onDestroy()
Activity的開(kāi)始:onCreate->onStart()->onResume();
Activity的結(jié)束:onPaused()->onStop()->onDestroy;
Activity的經(jīng)過(guò):是由界面可視化后,與用戶交互的過(guò)程。這里邊涉及到一個(gè)名詞——可視化,意思很簡(jiǎn)單,就是由界面不可見(jiàn)到可見(jiàn)的這個(gè)過(guò)程。
正常情況下Activity生命周期
這個(gè)圖其實(shí)已經(jīng)包含了所有正常情況下Activity生命周期的內(nèi)容。而正常的生命周期的回調(diào)也有很多種情況,接下來(lái)會(huì)逐一介紹。(注:接下來(lái)說(shuō)的啟動(dòng)都是指第一次啟動(dòng)和標(biāo)準(zhǔn)模式的啟動(dòng)方式)
1、正常的啟動(dòng)和關(guān)閉。
(1)啟動(dòng)Activity A,系統(tǒng)就會(huì)調(diào)用onCreate,創(chuàng)建這個(gè)Activity,創(chuàng)建成功后會(huì)馬上調(diào)用onStart,這時(shí)候Activity就已經(jīng)可見(jiàn)了,但還沒(méi)有出現(xiàn)在在前臺(tái),還無(wú)法交互,緊接著會(huì)調(diào)用onResume,這時(shí)候界面就已經(jīng)可見(jiàn)了,這時(shí)候這一次啟動(dòng)就已經(jīng)走完了;
(2)結(jié)束Activity A,會(huì)先調(diào)用onPause,調(diào)用完成后界面就不分不可見(jiàn)了,緊接著這時(shí)候會(huì)掉用onStop,調(diào)用完成后就完全看不見(jiàn)了,最后就會(huì)調(diào)用onDestroy去銷毀這個(gè)Activity A,這時(shí)候這個(gè)Activity就結(jié)束了。
2、啟動(dòng)Activity A后再?gòu)腁啟動(dòng)和結(jié)束Activity B過(guò)程中,Activity A的生命周期的回調(diào)。
(1)當(dāng)A啟動(dòng)好后,從A啟動(dòng)B,這時(shí)候A很明顯會(huì)被B遮住,所以從視覺(jué)上我們應(yīng)該可以猜到應(yīng)該會(huì)調(diào)用onPause和onStop,實(shí)際上也確實(shí)是這樣;
(2)結(jié)束B,這時(shí)候A就應(yīng)該重新可見(jiàn),系統(tǒng)便會(huì)給我們依次回調(diào)onRestart->onSatrt->onResume方法,這時(shí)候A的界面又重新可見(jiàn)了。
(3)注意:這里邊有兩個(gè)知識(shí)點(diǎn)比較特殊,(1)如果B的主題被設(shè)置被背景透明,那么從A啟動(dòng)B時(shí),A不會(huì)調(diào)用onStop方法,具體原因暫時(shí)還未深究;(2)A的onPause和B的onResume誰(shuí)先調(diào)用,從源碼中可以得到答案,應(yīng)該是A的onPause先調(diào)用,所以為了用戶體驗(yàn),我們不應(yīng)該在onPause中做耗時(shí)的操作。
注意:啟動(dòng)dialog并不會(huì)回調(diào)任何activity的生命周期
異常情況下的生命周期
上邊說(shuō)到正常的生命周期會(huì)有那么幾種情況,那什么叫不正常的呢?其實(shí)就是Activity在資源相關(guān)的系統(tǒng)配置發(fā)生改變或者系統(tǒng)內(nèi)存不足時(shí)被殺死,并重新創(chuàng)建的時(shí)候,這時(shí)候就不大相同了。接下來(lái)分析這兩種情況。
1、資源以及相關(guān)配置發(fā)生改變,被銷毀并重建
資源加載機(jī)制比較復(fù)雜,我暫時(shí)還沒(méi)有太多了解,這里也就不過(guò)多解釋;舉個(gè)出現(xiàn)這種情況的例子吧,比如程序有兩張圖片對(duì)應(yīng)橫屏和豎屏?xí)r加載,當(dāng)Activity從豎屏轉(zhuǎn)到橫屏?xí)r,由于系統(tǒng)配置發(fā)生改變,在默認(rèn)情況下,Activity就會(huì)被銷毀并重建,當(dāng)然我們也可以阻止重建該Activity。
(1)在這種情況下Activity的銷毀依然還是會(huì)調(diào)用onPause,onStop,onDestroy方法,同時(shí)還會(huì)調(diào)用onSaveInstanceState,通過(guò)參數(shù)Bundle來(lái)保存當(dāng)前Activity的狀態(tài),該方法的回調(diào)早onStop之前,和onPause沒(méi)有固定的順序;重建的時(shí)候除了會(huì)調(diào)用onCreate,onStart,onResume以外還會(huì)多調(diào)用一個(gè)onRestoreInstanceState方法,通過(guò)參數(shù)Bundle來(lái)恢復(fù)狀態(tài),該方法在onStart之后調(diào)用。值得注意的是,系統(tǒng)本身在這兩個(gè)方法里已經(jīng)為我們保存了一些數(shù)據(jù),例如View的數(shù)據(jù),通過(guò)查看源碼我們可以找到在View中也有onSaveInstanceState和onRestoreInstanceState方法,用來(lái)保存和恢復(fù)View中的一些數(shù)據(jù),而這個(gè)過(guò)程是由Activity通知Window,window通知decorView,decorView再一一通知子View來(lái)完成的,通知的過(guò)程和View的繪制和事件回調(diào)流程一致,這是一種委托的思想。
2、資源內(nèi)存不足導(dǎo)致低優(yōu)先級(jí)的Activity被銷毀。
這種情況不好模擬,但是他的數(shù)據(jù)恢復(fù)和第一種情況是完全一致的,而這里描述一下Activity的優(yōu)先級(jí),從高到低分為:
(1)前臺(tái)Activity——正在交互的
(2)可見(jiàn)但非前臺(tái)——例如彈出一個(gè)Dialog,無(wú)法直接交互的
(3)后臺(tái)Activity——被暫停的,執(zhí)行了onStop方法的
3、阻止配置改變時(shí)被銷毀重建的方法
我們可以在AndroidManifest.xml文件中給Activity指定configChanges屬性,并根據(jù)不同情況賦予不同的值即可保證改變時(shí)不被銷毀重建,下邊就舉幾個(gè)例子來(lái)說(shuō)明:
(1)當(dāng)我們只考慮屏幕旋轉(zhuǎn)引起的重啟時(shí),我們只保留豎屏或者橫屏,這樣就讓旋轉(zhuǎn)時(shí)不改變布局方向來(lái)保證不被銷毀重啟,我們可以給Activity指定screenOrientation屬性,屬性值如下:
android:screenOrientation="portrait"//保留豎屏
android:screenOrientation="landscape"//保留橫屏
該屬性涉及到橫豎屏的屬性值就有好多個(gè),其具體含義如下:
Value
Meaning
"unspecified"
默認(rèn)值 由系統(tǒng)來(lái)判斷顯示方向.判定的策略是和設(shè)備相關(guān)的,所以不同的設(shè)備會(huì)有不同的顯示方向
"landscape"
橫屏顯示(寬比高要長(zhǎng))
"portrait"
豎屏顯示(高比寬要長(zhǎng))
"user"
用戶當(dāng)前首選的方向
"behind"
和該Activity下面的那個(gè)Activity的方向一致(在Activity堆棧中的)
"sensor"
有物理的感應(yīng)器來(lái)決定。如果用戶旋轉(zhuǎn)設(shè)備這屏幕會(huì)橫豎屏切換
"nosensor"
忽略物理感應(yīng)器,這樣就不會(huì)隨著用戶旋轉(zhuǎn)設(shè)備而更改了 ( "unspecified"設(shè)置除外 )
(2)還有一種就是使用configChanges屬性,并設(shè)置為:
android:configChanges="orientation"
同時(shí)設(shè)置多個(gè)屬性值時(shí),只需用“|”隔開(kāi)即可。下邊還是看一下該屬性常用的屬性值的含義吧:如下:
Value
Meaning
"orientation"
屏幕方向發(fā)生了改變,例如旋轉(zhuǎn)手機(jī)屏幕
"locale"
本地位置放生改變,一般為切換了系統(tǒng)語(yǔ)言
"keyboardHidden"
鍵盤的可訪問(wèn)性發(fā)生了改變,例如用戶調(diào)出了鍵盤
"screenSize"
當(dāng)屏幕尺寸發(fā)生改變,例如屏幕旋轉(zhuǎn)也會(huì)導(dǎo)致屏幕尺寸發(fā)生改變,若minSdkVersion或者targetSdkVersion任一大于等于13,則就會(huì)引起重啟
"smallestScreenSize"
當(dāng)接入外接顯示器時(shí),若minSdkVersion或者targetSdkVersion任一大于等于13,則就會(huì)引起重啟
Activity的啟動(dòng)模式
1、啟動(dòng)模式介紹
Android系統(tǒng)為了保證資源不浪費(fèi),盡可能的不要?jiǎng)?chuàng)建多余的Activity,所以引入了啟動(dòng)模式,Actvity的啟動(dòng)模式包含:standard、singleTop、singleTask、singleInstance。說(shuō)到啟動(dòng)模式,必然就會(huì)涉及到任務(wù)棧的問(wèn)題,這是系統(tǒng)為我們提供的管理Activity的一個(gè)結(jié)構(gòu),棧的特點(diǎn)就是先進(jìn)后出。那Activity創(chuàng)建時(shí)是怎么進(jìn)棧的呢,這個(gè)就要看不同的啟動(dòng)模式,來(lái)區(qū)別對(duì)待了。
(1)standard:標(biāo)準(zhǔn)模式,這是系統(tǒng)默認(rèn)的啟動(dòng)模式。每次啟動(dòng)一個(gè)Activity都會(huì)重新創(chuàng)建一個(gè)Activity實(shí)例,不管這個(gè)Activity是否已經(jīng)存在實(shí)例。這時(shí)候被啟動(dòng)的Activity進(jìn)入的棧就是啟動(dòng)它的Activity所在的任務(wù)棧。當(dāng)我們使用ApplicationContext去啟動(dòng)standard模式的Activity時(shí)是會(huì)報(bào)錯(cuò)的,而ApplicationContext并沒(méi)有任務(wù)棧。解決辦法是為要啟動(dòng)的Activity指定一個(gè)FLAG_ACTIVITY_NEW_TASK標(biāo)記位,這時(shí)就能為新創(chuàng)建的Activity創(chuàng)建一個(gè)新的任務(wù)棧。
(2)SingleTop:棧頂復(fù)用模式。如果新的Activity的實(shí)例已經(jīng)位于棧頂,則不會(huì)被重新創(chuàng)建,只會(huì)回調(diào)onNewIntent方法,便可拿到當(dāng)前請(qǐng)求的信息。若不再棧頂,則依然會(huì)重新創(chuàng)建一個(gè)實(shí)例。
(3)singleTask:棧內(nèi)復(fù)用模式。這其實(shí)是一種單例模式,只要該Activity所需的任務(wù)棧中存在其實(shí)例,便不會(huì)重新創(chuàng)建該實(shí)例,只會(huì)回調(diào)onNewIntent方法,而在該Activity上的Activity會(huì)被移除掉,從而使該Activity移動(dòng)到棧頂。若不存在,便會(huì)在該Activity所需的任務(wù)棧中創(chuàng)建實(shí)例,若其所需的任務(wù)棧不存在,則會(huì)先創(chuàng)建該任務(wù)棧。但是使用ApplicationContext去啟動(dòng)一個(gè)SingleTask模式的Activity依舊會(huì)報(bào)錯(cuò)。其中說(shuō)到了Activity所需的任務(wù)棧,這個(gè)就是要使用TaskAffinity屬性來(lái)設(shè)定,默認(rèn)任務(wù)棧的名字都是包名,這個(gè)屬性只有和singleTask一起使用才有效。
(4)singleInstance:單實(shí)例模式。這個(gè)就是加強(qiáng)版的singleTask,他只會(huì)單獨(dú)存在于一個(gè)任務(wù)棧中。
2、啟動(dòng)模式的應(yīng)用場(chǎng)景
Mode
Use Case
standard
默認(rèn)都是使用該模式
singleTop
適合接受通知并啟動(dòng)的內(nèi)容展示頁(yè)面,好比新聞詳情界面,收到10個(gè)新聞推送,每個(gè)都要打開(kāi)新聞詳情,若打開(kāi)十次那肯定是不合適的。
singleTask
適合作為程序入口點(diǎn),例如瀏覽器的主界面。不管從多少個(gè)應(yīng)用啟動(dòng)瀏覽器,只會(huì)啟動(dòng)主界面一次,其余情況都會(huì)走onNewIntent,并且會(huì)清空主界面上面的其他頁(yè)面。
singleInstance
適合需要與程序分離開(kāi)的頁(yè)面。例如鬧鈴提醒,將鬧鈴提醒與鬧鈴設(shè)置分離。singleInstance不要用于中間頁(yè)面,如果用于中間頁(yè)面,跳轉(zhuǎn)會(huì)有問(wèn)題,比如:A -> B (singleInstance) -> C,完全退出后,在此啟動(dòng),首先打開(kāi)的是B。
Activity中常用的方法
1、生命周期中的各個(gè)方法;
2、finish()->關(guān)閉Activity;
3、onBackPressed()->按返回鍵回調(diào),默認(rèn)實(shí)現(xiàn)是finish掉Activity;
4、startActivity(...)->分別表示啟動(dòng)Activity;
5、startActivityForResult(...)->啟動(dòng)Activity并能接受啟動(dòng)的那個(gè)Activity回傳的參數(shù),接收參數(shù)使用onActivityResult(...)方法;
6、overridePendingTransition(...)->啟動(dòng)Activity的啟動(dòng)動(dòng)畫,必須緊跟在startActivity()或者finish()的后邊才有效;
7、runOnUiThread(...)->在主線程中運(yùn)行,通常在子線程中想要更新界面時(shí)使用,內(nèi)部使用Handler實(shí)現(xiàn);
8、getResource()->獲取資源,方便獲取圖片、顏色、尺寸、文本等資源;
9、registerReceiver(...)以及unregisterReceiver(...)->注冊(cè)廣播以及注銷廣播;
10、bindService()以及unbindService()->綁定服務(wù)以及解綁服務(wù);
11、getContentResolver()->用于獲取contentProvider數(shù)據(jù)。
總結(jié)
寫到這里基本上Activity的生命周期和啟動(dòng)模式就介紹的差不多了,如果說(shuō)還差什么的話,我覺(jué)得就應(yīng)該是Activity的標(biāo)志未以及IntentFilter的匹配規(guī)則,這兩個(gè)內(nèi)容留到Intent中再寫吧,這篇感覺(jué)已經(jīng)太多了。如果有任何不對(duì)的地方,請(qǐng)發(fā)我郵件,感謝~
參考資料
《Android開(kāi)發(fā)藝術(shù)探究》、Android developer training。
總結(jié)
以上是生活随笔為你收集整理的android activity 实际,Android学习感悟之Activity的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 某网站内容获取
- 下一篇: riak数据库php7,Riak (En