1.什麼是Activity
Activity是Android提供的四大元件之一,是進行Android開發必不可少的元件.Activity是一個界面的載體,它提供螢幕進行互動.可以把它與html頁面進行類比,html頁面由各種各樣的标簽組成,而Activity則可以由各種控件組成.每個Activity都會獲得一個用于繪制其使用者界面的視窗,視窗可以充滿哦螢幕也可以小于螢幕并浮動在其他視窗之上。
一個應用通常是由多個彼此松散聯系的Activity組成,一般會指定應用中的某個Activity為主活動,也就是說首次啟動應用時給使用者呈現的Activity。将Activity設為主活動的方法,如下面代碼所示需要在AndroidManifest檔案中添加以下内容
<application>
....
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
....
</application>
當然Activity之間可以進行互相跳轉,以便執行不同的操作。每當新Activity啟動時,舊的Activity便會停止,但是系統會在堆棧也就是傳回棧中保留該Activity。當新Activity啟動時,系統也會将其推送到傳回棧上,并取得使用者的操作焦點。當使用者完成目前Activity并按傳回按鈕時,系統就會從堆棧将其彈出銷毀,然後回複前一Activity.
當一個Activity因某個新Activity啟動而停止時,系統會通過該Activity的生命周期回調方法通知其這一狀态的變化。Activity因狀态變化每個變化可能有若幹種,每一種回調都會提供執行與該狀态相應的特定操作的機會
2.建立Activity
要建立Activity,必須建立Activity的子類。在子類中實作Activity在生命周期的各種狀态之間轉變時(例如建立 Activity、停止 Activity、恢複 Activity 或銷毀 Activity 時)系統調用的回調方法。Android Studio中建立項目預設建立的代碼為
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
onCreate()方法:必須實作的方法,系統在建立Activity時調用此方法。您應該在實作内初始化Activity的必要元件,必須在此方法調用setContentView(),用來定義Activity使用者界面布局(XML檔案)
3.在清單檔案中聲明Activity
每次建立的Activity都需要在AndroidManifest檔案中添加如下内容,并将元素添加為元素的子項
<manifest ... >
<application ... >
<activity android:name=".ExampleActivity" />
...
</application ... >
...
</manifest >
4.啟動Activity
作為主活動,在應用開啟的時候就會系統建立,而使用者不僅僅隻需要主活動界面,使用者需要界面的跳轉,而界面的跳轉也是其他活動界面(Activity)啟動。
4.1 Activity啟動方式
在Activity啟動中涉及到Intent這個API,在Android中提供了Intent機制來協助應用間的互動與通訊,Intent負責對應用中一次操作的動作、動作涉及資料、附加資料進行描述,Android則根據此Intent的描述,負責找到對應的元件,将 Intent傳遞給調用的元件,并完成元件的調用。
Intent不僅可用于應用程式之間,也可用于應用程式内部的Activity/Service之間的互動。是以,可以将Intent了解為不同元件之間通信的“媒介”,專門提供元件互相調用的相關資訊
Intent有七大屬性:
- component(元件):目的元件
- action(動作):用來表現意圖的行動
- category(類别):用來表現動作的類别
- data(資料):表示與動作要操縱的資料
- type(資料類型):對于data範例的描寫
- extras(擴充資訊):擴充資訊
- Flags(标志位):期望這個意圖的運作模式
顯示啟動
這應該用的是最多的一個啟動方式了,先在AndroidManifest.xml裡配置activity,然後進行如下操作:
Intent intent = new Intent(MainActivity.this,CloneActivity.class);
startActivity(intent);
隐式啟動
它與顯示啟動最大差別就是不需要在Intent的執行個體化中傳參, 但是需要在AndroidManifest.xml給該activity配置intentfilter屬性,啟動代碼如下
<intent-filter>
<action android:name="com.mangoer.activityreview"></action>
<category android:name="android.intent.category.DEFAULT"></category>
</intent-filter>
Intent intent = new Intent();
intent.setAction("com.mangoer.activityreview");
startActivity(intent);
隐式啟動的過濾過程如圖

一般顯示啟動用于同一APP内,隐式啟動用于啟動APP外部活動,如果有多個元件被比對成功,就會以對話框清單的方式讓使用者進行選擇。每個Intent中隻能指定一個action,但卻能指定多個category;類别越多,動作越具體,意圖越明确
在Intent添加類别可以添加多個類别,那就要求被比對的元件必須同時滿足這多個類别,才 能比對成功。操作Activity的時候,如果沒有類别,須加上預設類别
比如打開百度:
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
Uri data=Uri.parse("http://www.baidu.com");
intent.setData(data);
startActivity(intent);
有時候我們跳轉到别的activity後,希望能夠攜帶一些資料傳回到原activity,那就需要用到startActivityForResult
4.2 Activity啟動模式
啟動模式允許你去定義如何将一個activity的執行個體和目前任務棧進行關聯,有兩種方式來定義啟動模式
- 使用manifest檔案:在manifest檔案中聲明一個activity的時候指定launchMode屬性
- 使用Intent flag參數:當使用Intent啟動activity的時候,可以在Intent中加入flag來指定新啟動的activity如何與目前任務進行關聯
如果一個被啟動的activity在manifest裡定義了啟動模式,然後在使用Intent啟動的時候也設定了flag定義啟動模式,那麼Intent中的定義模式将會覆寫manifest中的定義
在manifest定義啟動模式
通過設定launchMode屬性來定義,有四種可選參數:
- standard: 這也是預設啟動模式,即标準模式;如果在該檔案中聲明activity的時候不指定這個參數值,這個activity就模式使用這種模式;它的意思是每啟動一個activity都會重新建立一個該activity的執行個體加入到目前任務中,會走完整的生命周期函數,就算任務中已經存在了這個activity的執行個體還是會建立。這樣就會出現上面說的一個activity在傳回棧中存在多個執行個體,這其實是非常消耗資源的。
- singleTop: 即棧頂複用模式,這個中文翻譯很有意思,給出了兩個很重要的點,棧頂和複用;也就是說如果要啟動的activity在傳回棧内已經存在了一個執行個體并且還處于棧頂的位置,那麼就不會在重新建立一個執行個體了,而是複用這個activity;複用展現在哪呢,就是調用這個activity的onNewIntent方法,而不會走onCreate-onStart-onResume這個建立邏輯了;如果這個activity不在棧頂,那麼還是會重新建立的。這種模式一般運用場景是一個Activity被頻繁推到棧頂的情況,比如IM聊天,有很多消息過來了,不可能每點選一個消息就去建立一個Activity;新聞推送,也不可能每次點選推送消息,就去建立一個Activity
-
singleTask: 即棧内複用模式,也是一種單例模式;當啟動的activity如果在棧内有執行個體,不管在不在棧頂都會複用這個執行個體,将其置于棧頂,調用這個activity的onNewIntent方法,并且将其上面的所有activity進行出棧處理,全部銷毀。
這裡有個注意點:android系統會檢測要啟動的activity的affinity和目前任務的affinity是否相同,如果相同就會把這個activity放入到目前任務中,不同的話就會建立一個新的任務。而同一個程式中所有的activity的affinity預設都是相同的,不同的程式是不同的,這樣啟動别的應用的這種模式的activity會建立一個新的任務,啟動自己應用的activity不會建立新的任務。這種模式運用場景比較少,一般用在比較特殊的頁面,比如使用者被簽退了,需要重新跳轉到登陸頁面,這時候需要将之前的頁面全部銷毀,因為跟session相關的資料需要重新初始化
-
singleInstance: 即單例模式,即這個activity自己獨享一個任務,所在的傳回棧裡面隻有這個activity。
比如給activity2設定singleInstance模式,從activity1跳轉到activity2,activity2跳轉到activity3,這時候按傳回鍵會傳回到activity1.因為Activity2獨自占用一個任務棧,而activity1和activity2共用一個任務棧
再舉一個例子,Android系統内置的浏覽器程式聲明自己浏覽網頁的Activity始終應該在一個獨立的任務當中打開,也就是通過在元素中設定"singleInstance"啟動模式來實作的。這意味着,當你的程式準備去打開Android内置浏覽器的時候,新打開的Activity并不會放入到你目前的任務中,而是會啟動一個新的任務。而如果浏覽器程式在背景已經存在一個任務了,則會把這個任務切換到前台,不會再重新建立。
使用Intent Flags 定義啟動模式
使用方法就是在使用startActivity的時候建構Intent,對Intent加入一個flag來改變Activity與任務的關聯模式
- FLAG_ACTIVITY_NEW_TASK: 當Intent對象包含這個标記時,系統會尋找或建立一個新的task來放置目标Activity,尋找時依據目标Activity的taskAffinity屬性進行比對,如果找到一個task的taskAffinity與之相同,就将目标Activity壓入此task中,如果查找無果,則建立一個新的task,并将該task的taskAffinity設定為目标Activity的taskActivity,将目标Activity放置于此task。注意,如果同一個應用中Activity的taskAffinity都使用預設值或都設定相同值時,應用内的Activity之間的跳轉使用這個标記是沒有意義的,因為目前應用task就是目标Activity最好的宿主
- FLAG_ACTIVITY_SINGLE_TOP: 設定了這個flag,如果要啟動的Activity在目前任務中已經存在了,并且還處于棧頂的位置,那麼就不會再次建立這個Activity的執行個體,而是直接調用它的onNewIntent()方法;否則會再建立這個activity;這種flag和在launchMode中指定"singleTop"模式所實作的效果是一樣的。
-
FLAG_ACTIVITY_CLEAR_TOP: 設定了這個flag,如果要啟動的Activity在目前任務的棧頂,就會銷毀這個執行個體并重新建立這個activity;如果不在棧頂,還是銷毀已存在的執行個體并清空這個執行個體上面的所有activity,最後重新建立這個activity。
如果将Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP兩個結合用,如果要啟動的Activity已經存在任務棧而且不在棧頂,那麼會清空這個activity以上的所有activity,并回調這個activity的onNewIntent,不會重新建立這個activity;如果處于棧頂,就直接回調onNewIntent
taskAffinity參數
affinity可以用于指定一個Activity更加願意依附于哪一個任務,在預設情況下,同一個應用程式中的所有Activity都具有相同的affinity,是以,這些Activity都更加傾向于運作在相同的任務當中。當然了,你也可以去改變每個Activity的affinity值,通過元素的taskAffinity屬性就可以實作了。
taskAffinity屬性接收一個字元串參數,你可以指定成任意的值(經我測試字元串中至少要包含一個),但必須不能和應用程式的包名相同,因為系統會使用包名來作為預設的affinity值。
通常可以與allowTaskReparenting屬性配合使用,設定為true時,Activity就擁有了一個轉移所在任務的能力。具體點來說,就是一個Activity現在是處于某個任務當中的,但是它與另外一個任務具有相同的affinity值,那麼當另外這個任務切換到前台的時候,該Activity就可以轉移到現在的這個任務當中。
5. 結束Activity
通過調用Activity的**finish()方法來結束Activity還可以通過調用finishActivity()**結束之前啟動的活動
關于finishActivity()的了解:
你通過 MainActivity 來啟動 ActivityA (使用 startActivityForResult 方法),那麼你在 MainActivity 這個類中需要重寫 onActivityResult() 這個方法,
然後,你可以在 onActivityResult() 中通過 finishActivity() 方法去結束掉 ActivityA
6. 管理Activity生命周期
周期即活動從開始到結束所經曆的各種狀态。生命周期即活動從開始到結束所經曆的各個狀态。從一個狀态到另一個狀态的轉變,從無到有再到無,這樣一個過程中所經曆的狀态就叫做生命周期。
Activity本質上有四種狀态:
- 運作(Active/Running): Activity處于活動狀态,此時Activity處于棧頂,是可見狀态,可以與使用者進行互動
- 暫停(Paused): 當Activity失去焦點時,或被一個新的非全面屏的Activity,或被一個透明的Activity放置在棧頂時,Activity就轉化為Paused狀态。此刻并不會被銷毀,隻是失去了與使用者互動的能力,其所有的狀态資訊及其成員變量都還在,隻有在系統記憶體緊張的情況下,才有可能被系統回收掉
- 停止(Stopped): 當Activity被系統完全覆寫時,被覆寫的Activity就會進入Stopped狀态,此時已不在可見,但是資源還是沒有被收回
- 系統回收(Killed): 當Activity被系統回收掉,Activity就處于Killed狀态,它所儲存的資訊和成員變量都不在了。
如果一個活動在處于停止或者暫停的狀态下,系統記憶體缺乏時會将其結束(finish)或者殺死(kill)。這種非正常情況下,系統在殺死或者結束之前會調用**onSaveInstance()方法來儲存資訊,同時,當Activity被移動到前台時,重新啟動該Activity并調用onRestoreInstance()**方法加載保留的資訊,以保持原有的狀态。
-
Activity 的整個生命周期發生在 onCreate() 調用與 onDestroy() 調用之間。
您的 Activity 應在 onCreate()中執行“全局”狀态設定(例如定義布局),并釋放 onDestroy()中的所有其餘資源。例如,如果您的 Activity 有一個在背景運作的線程,用于從網絡上下載下傳資料,它可能會在onCreate() 中建立該線程,然後在onDestroy() 中停止該線程。
-
Activity 的可見生命周期發生在 onStart() 調用與 onStop() 調用之間。
在這段時間,使用者可以在螢幕上看到 Activity 并與其互動。例如,當一個新 Activity 啟動,并且此 Activity 不再可見時,系統會調用onStop()。您可以在調用這兩個方法之間保留向使用者顯示 Activity 所需的資源。例如,您可以在onStart() 中注冊一個 BroadcastReceiver 以監控影響 UI的變化,并在使用者無法再看到您顯示的内容時在 onStop()中将其取消注冊。在 Activity 的整個生命周期,當 Activity 在對使用者可見和隐藏兩種狀态中交替變化時,系統可能會多次調用 onStart() 和 onStop()。
-
Activity 的前台生命周期發生在 onResume() 調用與 onPause() 調用之間。
在這段時間,Activity 位于螢幕上的所有其他 Activity 之前,并具有使用者輸入焦點。Activity 可頻繁轉入和轉出前台 — 例如,當裝置轉入休眠狀态或出現對話框時,系統會調用 onPause()。由于此狀态可能經常發生轉變,是以這兩個方法中應采用适度輕量級的代碼,以避免因轉變速度慢而讓使用者等待。
小結:
當Activity啟動時,依次會調用onCreate(),onStart(),onResume(),而當Activity退居背景時(不可見,點選Home或者被新的Activity完全覆寫),onPause()和onStop()會依次被調用。當Activity重新回到前台(從桌面回到原Activity或者被覆寫後又回到原Activity)時,onRestart(),onStart(),onResume()會依次被調用。當Activity退出銷毀時(點選back鍵),**onPause(),onStop(),onDestroy()**會依次被調用,到此Activity的整個生命周期方法回調完成。
參考:
- activity的四種狀态說明
- Activity開發–掌握Activity隐式顯示啟動方法 scheme跳轉協定 生命周期及啟動模式配置
- Android Activity詳解