Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android之Activity總結

Android之Activity總結

編輯:關於Android編程

1.Activity簡介

Activity是Android一個非常重要的用戶接口(四大組件之一),是可見的,主要是用戶和應用程序之間進行交互的接口。在每個Activity中都可以放很多控件,所以也可以把Activity看作控件的容器。

2.Activity生命周期

img

- onCreate:主要執行初始化工作,比如用setContentView加載布局界面
- onStart:Activity由不可見變為可見,但是不在前台,不可以與用戶進行交互
- onResume:使Activity位於返回棧的頂端,並出現在前台,可與用戶進行交互
- onRestart:Activity的重啟,由不可見變為可見
- onPause:表明Activity正在停止,正常情況下onStop會緊接著調用。但是也有特殊情況,若這個時候需要快速的揮刀當前Activity,那麼onResume也會被調用。這個方法的執行一定要快,不然會影響棧頂的Activity的使用。
- onStop:Activity由部分不可見變為完全不可見,可做一些重量級的回收工作,同樣不能很耗時。
- onDestory:銷毀Activity並釋放資源。

其中onCreate和onDestory為完整的生命周期,onStart和onStop為可見生命周期,onResume和onPause為前台生命周期。

注意點

當用戶打開新的Activity或切換回到桌面的時候,回調為onPause->onStop,但是若Activity采用的為透明主題,則不會回調onStop。 一般情況下,Activity有不可見變為可見,onRestart才會調用。 onStart和onStop控制Activity在可見和不可見的狀態之間轉換,onResume和onPause控制Activity在前台或非前台之間轉換。 當由Activity A ->Activity B時,回調的順序為onPause(A)->onCreate(B)->onStart(B)->onStop(A),因此不可以在onPause上做重量級操作。 如果應用長時間處於stopped狀態並且此時系統內存極為緊張的時候,系統就會回收Activity,此時系統在回收之前會回調onSaveInstanceState方法來保存應用的數據Bundle。當該Activity重新創建的時候,保存的Bundle數據就會傳遞到onRestoreSaveInstanceState方法和onCreate方法中,這就是onCreate方法中Bundle savedInstanceState參數的來源(onRestoreInstanceState的bundle參數也會傳遞到onCreate方法中,你也可以選擇在onCreate方法中做數據還原)。

onSaveInstanceState方法和onRestoreInstanceState方法“不一定”是成對的被調用的。

onSaveInstanceState的調用遵循一個重要原則,即當系統“未經你許可”時銷毀了你的activity,則onSaveInstanceState會被系統調用,這是系統的責任,因為它必須要提供一個機會讓你保存你的數據。

onRestoreInstanceState被調用的前提是,activity“確實”被系統銷毀了,而如果僅僅是停留在有這種可能性的情況下,則該方法不會被調用,例如,當正在顯示activity的時候,用戶按下HOME鍵回到主界面,然後用戶緊接著又返回到activity,這種情況下activity一般不會因為內存的原因被系統銷毀,故activity的onRestoreInstanceState方法不會被執行。

3.異常生命周期

1.資源相關的系統配置發生改變導致Activity被殺死並重建

資源相關的系統配置發生改變,舉個栗子。當前Activity處於豎屏狀態的時候突然轉成橫屏,系統配置發生了改變,Activity就會銷毀並且重建,其onPause, onStop, onDestory均會被調用。因為實在異常情況下終止的,所以系統會調用onSaveInstanceState來保存當前Activity狀態。這個方法是在onStop之前,與onPause沒有固定的時序關系。當Activity重建的時候系統會把onSaveInstanceState所保存的Bundle作為對象傳遞給onRestoreInstanceState和onCreate方法。

注:

View的源碼中每個View都有onSaveInstanceState和onRestoreInstanceState這兩個方法。 接收位置可以是onRestoreInstanceState和onCreate方法,區別是:onRestoreInstanceState如果被調用,參數Bundle一定是有值的,在onCreate中需要判斷參數是否為null。 onSaveInstanceState只有在Activity即將銷毀並有機會重新顯示時才會調用,正常銷毀的Activity生命周期中不會調用,比如:旋轉屏幕,按Home鍵,啟動新Activity等。

2.資源內存不足導致低優先級的Acitvity被殺死

Activity優先級

前台Activity——正在和用戶交互的Activity,優先級最高 可見但非前台Activity——Activity中彈出的對話框導致Activity可見但無法交互 後台Activity——已經被暫停的Activity,優先級最低

系統內存不足是,會按照以上順序殺死Activity,並通過onSaveInstanceState和onRestoreInstanceState這兩個方法來存儲和恢復數據。

不讓Activity重新創建的方法

系統配置有很多內容,當某項改變時,我們不想讓Activity重新創建可以在AndroidMainfest中給Activity指定configChanges屬性。比如

 android:configChanges="orientation"1

configChanges屬性非常多,具體可參考官方文檔

常用的有locale, orientation和keyboardHidden這三個。

4.Activity任務棧和四種啟動模式

應用內的Activity是被任務棧Task來管理的,一個Task中的Activity可以來自不同的應用,同一個應用的Activity也可能不在同一個Task中。默認情況下,任務棧依據棧的後進先出原則管理Activity,但是Activity可以設置一些“特權”打破默認的規則,主要是通過在AndroidManifest文件中的屬性android:launchMode或者通過Intent的flag來設置。

standard:默認的啟動模式,該模式下會生成一個新的Activity,同時將該Activity實例壓入到棧中(不管該Activity是否已經存在在Task棧中,都是采用new操作)。例如: 棧中順序是A B C D ,此時D通過Intent跳轉到A,那麼棧中結構就變成 A B C D A,點擊返回按鈕的 顯示順序是 D C B A,依次摧毀。

singleTop:在singleTop模式下,如果當前Activity D位於棧頂,此時通過Intent跳轉到它本身的Activity(即D),那麼不會重新創建一個新的D實例(走onNewIntent()),所以棧中的結構依舊為A B C D,如果跳轉到B,那麼由於B不處於棧頂,所以會新建一個B實例並壓入到棧中,結構就變成了A B C D B。應用實例:三條推送,點進去都是一個activity。

singleTask:在singleTask模式下,Task棧中只能有一個對應Activity的實例。例如:現在棧的結構為A B C D,此時D通過Intent跳轉到B(走onNewIntent()),則棧的結構變成了:A B。其中的C和D被棧彈出銷毀了,也就是說位於B之上的實例都被銷毀了。如果系統已經存在一個實例,系統就會將請求發送到這個實例上,但這個時候,系統就不會再調用通常情況下我們處理請求數據的onCreate方法,而是調用onNewIntent方法。通常應用於首頁,首頁肯定得在棧底部,也只能在棧底部。

singleInstance:singleInstance模式下會將打開的Activity壓入一個新建的任務棧中。例如:Task棧1中結構為:A B C,C通過Intent跳轉到了D(D的啟動模式為singleInstance),那麼則會新建一個Task 棧2,棧1中結構依舊為A B C,棧2中結構為D,此時屏幕中顯示D,之後D通過Intent跳轉到D,棧2中不會壓入新的D,所以2個棧中的情況沒發生改變。如果D跳轉到了C,那麼就會根據C對應的啟動模式在棧1中進行對應的操作,C如果為standard,那麼D跳轉到C,棧1的結構為A B C C,此時點擊返回按鈕,還是在C,棧1的結構變為A B C,而不會回到D。

Intent Flag啟動模式

(1)Intent.FLAG_ACTIVITY_NEW_TASK:使用一個新的task來啟動Activity,一般用在service中啟動Activity的場景,因為service中並不存在Activity棧。

(2)Intent.FLAG_ACTIVITY_SINGLE_TOP:類似andoid:launchMode=”singleTop”

(3)Intent.FLAG_ACTIVITY_CLEAR_TOP:類似andoid:launchMode=”singleTask”

(4)Intent.FLAG_ACTIVITY_NO_HISTORY:使用這種模式啟動Activity,當該Activity啟動其他Activity後,該Activity就消失了,不會保留在task棧中。例如A B,在B中以這種模式啟動C,C再啟動D,則當前的task棧變成A B D。

清空任務棧

(1)clearTaskOnLaunch:每次返回該Activity時,都將該Activity之上的所有Activity都清除。通過這個屬性可以讓task每次在初始化的時候都只有這一個Activity。

(2)finishOnTaskLaunch:clearTaskOnLaunch作用在別的Activity身上,而finishOnTaskLaunch作用在自己身上。通過這個屬性,當離開這個Activity所在的task,那麼當用戶再返回時,該Activity就會被finish掉。 [暫時還不明白這個有什麼作用]

(3)alwaysRetainTaskState:如果將Activity的這個屬性設置為true,那麼該Activity所在的task將不接受任何清理命令,一直保持當前task狀態,相當於給了task一道”免死金牌”。

5.IntentFilter的匹配規則

(1)IntentFilter中的過濾信息有action、category、data,為了匹配過濾列表,需要同時匹配過濾列表中的action、category、data信息,否則匹配失敗。一個過濾列表中的action、category、data可以有多個,所有的action、category、data分別構成不同類別,同一類別的信息共同約束當前類別的匹配過程。只有一個Intent同時匹配action類別、category類別和data類別才算完全匹配,只有完全匹配才能成功啟動目標Activity。此外,一個Activity中可以有多個intent-filter,一個Intent只要能匹配任何一組intenf-filter即可成功啟動對應的Activity。


 






 

(2)action匹配規則

只要Intent中的action能夠和過濾規則中的任何一個action相同即可匹配成功,action匹配區分大小寫。

(3)category匹配規則

Intent中如果有category那麼所有的category都必須和過濾規則中的其中一個category相同,如果沒有category的話那麼就是默認的category,即android.intent.category.DEFAULT,所以為了Activity能夠接收隱式調用,配置多個category的時候必須加上默認的category。

(4)data匹配規則

data的結構很復雜,語法大致如下:


主要由mimeType和URI組成,其中mimeType代表媒體類型,而URI的結構也復雜,大致如下:

://:/[]|[]|[pathPattern]

例如content://com.example.project:200/folder/subfolder/etc

scheme、host、port分別表示URI的模式、主機名和端口號,其中如果scheme或者host未指定那麼URI就無效。

path、pathPattern、pathPrefix都是表示路徑信息,其中path表示完整的路徑信息,pathPrefix表示路徑的前綴信息;pathPattern表示完整的路徑,但是它裡面包含了通配符(*)。

data匹配規則:Intent中必須含有data數據,並且data數據能夠完全匹配過濾規則中的某一個data。

URI有默認的scheme!

如果過濾規則中的mimeType指定為image/或者text/等這種類型的話,那麼即使過濾規則中沒有指定URI,URI有默認的scheme是content和file!如果過濾規則中指定了scheme的話那就不是默認的scheme了。

//URI有默認值

    
    ...

//URI默認值被覆蓋

    
    ...

如果要為Intent指定完整的data,必須要調用setDataAndType方法!

不能先調用setData然後調用setType,因為這兩個方法會彼此清除對方的值。

intent.setDataAndType(Uri.parse("file://abc"), "image/png");

data的下面兩種寫法作用是一樣的:


    



    
    

如何判斷是否有Activity能夠匹配我們的隱式Intent?

(1)PackageManager的resolveActivity方法或者Intent的resolveActivity方法:如果找不到就會返回null

(2)PackageManager的queryIntentActivities方法:它返回所有成功匹配的Activity信息

針對Service和BroadcastReceiver等組件,PackageManager同樣提供了類似的方法去獲取成功匹配的組件信息,例如queryIntentServices、queryBroadcastReceivers等方法

有一類action和category比較重要,它們在一起用來標明這是一個入口Activity,並且會出現在系統的應用列表中。


    
    

6.Activity的構成

Activity的構成不是一個Activity對象加上一個布局文件那麼簡單,在Activity和開發人員中間還隔著兩層。實際上視圖會被設置給一個Window類,Window類中有一個DecorView,這就是整個窗口的頂級視圖。開發人員設置的布局會被設置到這個DecorView的mContentParent布局中。

這樣子,用戶界面就被添加到了系統布局中,而系統布局會為我們設置好標題欄區域等。

Activity->
PhoneWindow->DecorView->
DefaultLayout->ViewGroup:mContentParent->用戶自己的xml布局
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved