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