Android Activity詳解

當(dāng)你決定要學(xué)習(xí)android的時(shí)候,這時(shí)候就需要制定一個(gè)學(xué)習(xí)路線,而我們應(yīng)該從哪里入手呢?你可以想象一下,當(dāng)你打開一個(gè)app的時(shí)候,第一眼看到的不是高明的算法或出色的架構(gòu),而是界面。那么我們今天的主題自然就要從看的到的界面入手了。

我們將學(xué)到什么

一、什么是活動(dòng)(Activity)
二、Activity的創(chuàng)建方法
三、Activity的生命周期
四、Activity之間的通信
五、Activity的棧式管理
六、Activity的啟動(dòng)模式
七、Activity使用小技巧

一、什么是活動(dòng)(Activity)

活動(dòng)(Activity)是最容易吸引到用戶的地方了,它是一種可以包含用戶界面的組件,
主要用于和用戶進(jìn)行交互。一個(gè)應(yīng)用程序中可以包含零個(gè)或多個(gè)活動(dòng),但不包含任何活動(dòng)的
應(yīng)用程序很少見,誰也不想讓自己的應(yīng)用永遠(yuǎn)無法被用戶看到吧?

二、Activity的創(chuàng)建方法

創(chuàng)建一個(gè)活動(dòng)的方法有兩種,自動(dòng)創(chuàng)建和手動(dòng)創(chuàng)建。
自動(dòng)創(chuàng)建activity

自動(dòng)創(chuàng)建activity1
自動(dòng)創(chuàng)建activity2

按照上面兩張圖一步步做就可以了,新手們最好選擇Empty Activity(空活動(dòng))

手動(dòng)創(chuàng)建activity
第一步
先建一個(gè)class,包名處右擊鼠標(biāo),選擇New -> Java Class

手動(dòng)創(chuàng)建activity1

然后會(huì)出現(xiàn)這個(gè)界面,取個(gè)名字就可以點(diǎn)OK了

手動(dòng)創(chuàng)建activity2

會(huì)出現(xiàn)這個(gè)界面

手動(dòng)創(chuàng)建activity3

第二步
在layout里New一個(gè)layout resource file

手動(dòng)創(chuàng)建activity4

出現(xiàn)這個(gè)界面,取個(gè)名字點(diǎn)擊OK

手動(dòng)創(chuàng)建activity5

然后我們的layout就建好了

手動(dòng)創(chuàng)建activity6

第三步
將建好的layout添加到class中
1.繼承AppCompatActivity(以前是直接繼承Activity,兩者用法差別不大)
2.重寫OnCreate方法
3.設(shè)置layout

手動(dòng)創(chuàng)建activity7

第四步
在AndroidManifest中注冊(cè),打開app -> manifests -> AndroidManifests
加入下圖中圈出的代碼

手動(dòng)創(chuàng)建activity8

由于最外層的<manifest>標(biāo)簽中已經(jīng)通過 package 屬性指定了程序的包名是
com.example.administrator,因此在注冊(cè)活動(dòng)時(shí)這一部分就可以省略了,直接使用.ThirdActivity就足夠了,全稱為com.example.administrator.ThirdActivity

MainActivity中的有兩句聲明,說明了MainActivity是我們這個(gè)程序的主活動(dòng)。

<intent-filter>
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

如果你想讓 ThirdActivity作為我們這個(gè)程序的主活動(dòng),即點(diǎn)擊桌面應(yīng)用程序圖標(biāo)時(shí)首先打開的就是這個(gè)活動(dòng),可以把這兩句聲明寫到ThirdActivity中,這個(gè)聲明在一個(gè)程序中最多只能有一個(gè)
另外需要注意,如果你的應(yīng)用程序中沒有聲明任何一個(gè)活動(dòng)作為主活動(dòng),這個(gè)程序仍然是可以正常安裝的,只是你無法在啟動(dòng)器中看到或者打開這個(gè)程序。這種程序一般都是作為第三方服務(wù)供其他的應(yīng)用在內(nèi)部進(jìn)行調(diào)用的,如支付寶快捷支付服務(wù)。
這樣我們就手動(dòng)創(chuàng)建好一個(gè)activity了。

三、Activity的生命周期

說道activity的生命周期就不得不看一張超級(jí)經(jīng)典的圖了

activity的生命周期

這張圖當(dāng)年在我剛接觸android的時(shí)候可是給了我一段很痛苦的回憶,簡(jiǎn)單的來說就是看不懂,所以我就用小白一點(diǎn)的語言來總結(jié)一下吧。
首先,我們可以把a(bǔ)ctivity看成是一個(gè)人,人都有出生到死亡的過程,activity也是有這個(gè)過程,而人在特定的時(shí)間會(huì)干一些特定的事,比如6歲上小學(xué),12歲上中學(xué),18歲上大學(xué),activity則是把這些時(shí)間點(diǎn)交給了我們這些程序員,而我們可以決定它在這些時(shí)間點(diǎn)上干什么事。
activity有多少個(gè)我們可以決定的時(shí)間點(diǎn)呢?
1.onCreate() -- 創(chuàng)建時(shí)
這個(gè)方法是只在activity被創(chuàng)建時(shí)調(diào)用一次,可以做一些數(shù)據(jù)的初始化工作。。
2.onStart -- 開始時(shí)
這個(gè)方法在每次啟動(dòng)activity時(shí)調(diào)用,變成“用戶可見不可交互”的狀態(tài)。
3.onResume() -- 重啟時(shí)
變成和用戶可交互的狀態(tài),將當(dāng)前Activity在放在棧的最上端
4.onPaues() -- 暫停時(shí)
到這一步是可見但不可交互的,系統(tǒng)會(huì)停止動(dòng)畫等消耗CPU的事情。從上文的描述已經(jīng)知道,應(yīng)該在這里保存你的一些數(shù)據(jù),因?yàn)檫@個(gè)時(shí)候你的程序的優(yōu)先級(jí)降 低,有可能被系統(tǒng)收回。在這里保存的數(shù)據(jù),應(yīng)該在onResume里讀出來。
5.onStop() -- 停止時(shí)
變得不可見 ,被下一個(gè)activity覆蓋了
6.onDestroy() -- 銷毀時(shí)
這里主要是做一些釋放資源的操作。

四、Activity之間的通信

在一個(gè)項(xiàng)目中,我們會(huì)用到很多的activity,因此我們需要一種特別的機(jī)制幫助我們?cè)?Activity 之間傳遞消息。

Intent的使用

Intent是一種消息傳遞的機(jī)制,它負(fù)責(zé)對(duì)操作的動(dòng)作、動(dòng)作涉及數(shù)據(jù)、附加數(shù)據(jù)進(jìn)行描述,Android則根據(jù)此Intent的描述,負(fù)責(zé)找到對(duì)應(yīng)的組件,將 Intent傳遞給調(diào)用的組件,并完成組件的調(diào)用。
我們有兩種形式來使用Intent:
1.使用顯式Intent
通過指定具體的組件類,通知應(yīng)用啟動(dòng)對(duì)應(yīng)的組件。
比如我們從MainActivity跳轉(zhuǎn)到SecondActivity,并傳一個(gè)字符串。

MainActivity中的代碼

Intent intent = new Intent();
intent.setClass(MainActivity.this,SecondAcvivity.class);
intent.putExtra("values","傳個(gè)值");
startActivity(intent);

SecondActivity中的代碼

Intent intent = getIntent();
String values = intent.getStringExtra("values");

2.使用隱式Intent
相比于顯式 Intent,隱式 Intent 則含蓄了許多,它并不明確指出我們想要啟動(dòng)哪一個(gè)活動(dòng),而是指定了一系列更為抽象的 action和 category等信息,然后交由系統(tǒng)去分析這個(gè) Intent,并幫我們找出合適的活動(dòng)去啟動(dòng)。
什么叫做合適的活動(dòng)呢?簡(jiǎn)單來說就是可以響應(yīng)我們這個(gè)隱式 Intent的活動(dòng),那么目前activity 可以響應(yīng)什么樣的隱式 Intent 呢?額,現(xiàn)在好像還什么都響應(yīng)不了,不過很快就會(huì)有了。

我們還是要從MainActivity跳轉(zhuǎn)到SecondActivity,這時(shí)我們可以通過在<activity>標(biāo)簽下配置<intent-filter>的內(nèi)容,可以指定當(dāng)前活動(dòng)能夠響應(yīng)的 action
和 category,打開 AndroidManifest.xml,添加如下代碼

<activity android:name=".SecondActivity" >
<intent-filter>
<action android:name="com.example.administrator.ACTION_START" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>

在<action>標(biāo)簽中我們指明了當(dāng)前活動(dòng)可以響應(yīng) com.example.activitytest.ACTION_
START這個(gè) action,而<category>標(biāo)簽則包含了一些附加信息,更精確地指明了當(dāng)前的活動(dòng)能夠響應(yīng)的 Intent 中還可能帶有的 category。只有<action>和<category>中的內(nèi)容同時(shí)能夠匹配上 Intent 中指定的 action 和 category 時(shí),這個(gè)活動(dòng)才能響應(yīng)該 Intent。
然后我們修改MainActivity中的Intent代碼:

Intent intent = new Intent("com.example.administrator.ACTION_START");
startActivity(intent);

可以看到,我們使用了 Intent 的另一個(gè)構(gòu)造函數(shù),直接將 action 的字符串傳了進(jìn)去,表
明我們想要啟動(dòng)能夠響應(yīng) com.example.activitytest.ACTION_START這個(gè) action 的活動(dòng)。那前面不是說要<action>和<category>同時(shí)匹配上才能響應(yīng)的嗎?怎么沒看到哪里有指定category 呢?這是因?yàn)?android.intent.category.DEFAULT 是一種默認(rèn)的 category,在調(diào)用startActivity()方法的時(shí)候會(huì)自動(dòng)將這個(gè) category 添加到 Intent 中。

這種方式同樣可以啟動(dòng) SecondActivity。不同的是,這次你是使用了隱式 Intent 的方式來啟動(dòng)的。

更多隱式 Intent 的用法
使用隱式 Intent,我們不僅可以啟動(dòng)自己程序內(nèi)的活動(dòng),還可以啟動(dòng)其他程序的活動(dòng),
這使得 Android 多個(gè)應(yīng)用程序之間的功能共享成為了可能。比如說你的應(yīng)用程序中需要展示一個(gè)網(wǎng)頁,這時(shí)你沒有必要自己去實(shí)現(xiàn)一個(gè)瀏覽器(事實(shí)上也不太可能),而是只需要調(diào)用系統(tǒng)的瀏覽器來打開這個(gè)網(wǎng)頁就行了。

Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("http://www.baidu.com"));
startActivity(intent);

這里我們首先指定了 Intent 的 action 是 Intent.ACTION_VIEW,這是一個(gè) Android 系統(tǒng)內(nèi)置的動(dòng)作,其常量值為 android.intent.action.VIEW。然后通過 Uri.parse()方法,將一個(gè)網(wǎng)址字符串解析成一個(gè) Uri 對(duì)象,再調(diào)用 Intent的 setData()方法將這個(gè) Uri 對(duì)象傳遞進(jìn)去。

與此對(duì)應(yīng),我們還可以在<intent-filter>標(biāo)簽中再配置一個(gè)<data>標(biāo)簽,用于更精確地指
定當(dāng)前活動(dòng)能夠響應(yīng)什么類型的數(shù)據(jù)。<data>標(biāo)簽中主要可以配置以下內(nèi)容。

  1. android:scheme
    用于指定數(shù)據(jù)的協(xié)議部分,如上例中的 http 部分。
  2. android:host
    用于指定數(shù)據(jù)的主機(jī)名部分,如上例中的 www.baidu.com部分。
  3. android:port
    用于指定數(shù)據(jù)的端口部分,一般緊隨在主機(jī)名之后。
  4. android:path
    用于指定主機(jī)名和端口之后的部分,如一段網(wǎng)址中跟在域名之后的內(nèi)容。
  5. android:mimeType
    用于指定可以處理的數(shù)據(jù)類型,允許使用通配符的方式進(jìn)行指定。

只有<data>標(biāo)簽中指定的內(nèi)容和 Intent 中攜帶的 Data完全一致時(shí),當(dāng)前活動(dòng)才能夠響應(yīng)該 Intent。不過一般在<data>標(biāo)簽中都不會(huì)指定過多的內(nèi)容,如上面瀏覽器示例中,其實(shí)只需要指定 android:scheme 為 http,就可以響應(yīng)所有的 http 協(xié)議的 Intent 了。

返回?cái)?shù)據(jù)給上一個(gè)活動(dòng)
既然可以傳遞數(shù)據(jù)給下一個(gè)活動(dòng),那么能不能夠返回?cái)?shù)據(jù)給上一個(gè)活動(dòng)呢?答案是肯定的。不過不同的是,返回上一個(gè)活動(dòng)只需要按一下 Back 鍵就可以了,并沒有一個(gè)用于啟動(dòng)活動(dòng) Intent 來傳遞數(shù)據(jù)。通過查閱文檔你會(huì)發(fā)現(xiàn),Activity 中還有一個(gè)startActivityForResult()方法也是用于啟動(dòng)活動(dòng)的,但這個(gè)方法期望在活動(dòng)銷毀的時(shí)候能夠返回一個(gè)結(jié)果給上一個(gè)活動(dòng)。毫無疑問,這就是我們所需要的。

startActivityForResult()方法接收兩個(gè)參數(shù),第一個(gè)參數(shù)還是 Intent,第二個(gè)參數(shù)是請(qǐng)求碼,用于在之后的回調(diào)中判斷數(shù)據(jù)的來源.代碼如下所示:

Intent intent = new Intent(MainActivity.this, SecondActivity.class);
startActivityForResult(intent, 1);

返回代碼如下

Intent intent = new Intent();
intent.putExtra("data_return", "Hello MainActivity");
setResult(RESULT_OK, intent);
finish();

可以看到,我們還是構(gòu)建了一個(gè) Intent,只不過這個(gè) Intent 僅僅是用于傳遞數(shù)據(jù)而已,
它沒有指定任何的“意圖”。緊接著把要傳遞的數(shù)據(jù)存放在 Intent 中,然后調(diào)用了 setResult()方法。這個(gè)方法非常重要,是專門用于向上一個(gè)活動(dòng)返回?cái)?shù)據(jù)的。setResult()方法接收兩個(gè)參數(shù),第一個(gè)參數(shù)用于向上一個(gè)活動(dòng)返回處理結(jié)果,一般只使用RESULT_OKRESULT_CANCELED這兩個(gè)值,第二個(gè)參數(shù)則是把帶有數(shù)據(jù)的 Intent 傳遞回去,然后調(diào)用了 finish()方法來銷毀當(dāng)前活動(dòng)。

由于我們是使用 startActivityForResult()方法來啟動(dòng) SecondActivity 的,在 SecondActivity被銷毀之后會(huì)回調(diào)上一個(gè)活動(dòng)的 onActivityResult()方法,因此我們需要在 FirstActivity 中重寫這個(gè)方法來得到返回的數(shù)據(jù),如下所示:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case 1:
if (resultCode == RESULT_OK) {
String returnedData = data.getStringExtra("data_return");
Log.d("FirstActivity", returnedData);
}
break;
default:
}
}

onActivityResult()方法帶有三個(gè)參數(shù):
第一個(gè)參數(shù) requestCode,即我們?cè)趩?dòng)活動(dòng)時(shí)傳入的請(qǐng)求碼。
第二個(gè)參數(shù) resultCode,即我們?cè)诜祷財(cái)?shù)據(jù)時(shí)傳入的處理結(jié)果。
第三個(gè)參數(shù) data,即攜帶著返回?cái)?shù)據(jù)的 Intent。
由于在一個(gè)活動(dòng)中有可能調(diào)用 startActivityForResult()方法去啟動(dòng)很多不同的活動(dòng),每一個(gè)活動(dòng)返回的數(shù)據(jù)都會(huì)回調(diào)到 onActivityResult()這個(gè)方法中,因此我們首先要做的就是通過檢查 requestCode 的值來判斷數(shù)據(jù)來源。確定數(shù)據(jù)是從SecondActivity 返回的之后,我們?cè)偻ㄟ^ resultCode 的值來判斷處理結(jié)果是否成功。最后從data中取值并打印出來,這樣就完成了向上一個(gè)活動(dòng)返回?cái)?shù)據(jù)的工作。

五、Activity的棧式管理

Android針對(duì)Activity的管理使用的是棧,就是說某一個(gè)時(shí)刻只有一個(gè)Activity處在棧頂,當(dāng)這個(gè)Activity被銷毀后,下面的Activity才有可能浮到棧頂,或者有一個(gè)新的Activity被創(chuàng)建出來,則舊的Activity就被壓棧沉下去了。Activity是Android程序的表現(xiàn)層。程序的每一個(gè)顯示屏幕就是一個(gè)Activity。正在運(yùn)行的Activity處在棧的最頂端,它是運(yùn)行狀態(tài)的。

當(dāng)在程序中調(diào)用 Activity.finish()方法時(shí),結(jié)果和用戶按下 BACK 鍵一樣:它告訴 Activity Manager該Activity實(shí)例可以被“回收”。隨后 Activity Manager 激活處于棧第二層的 Activity ,把原 Activity 壓入到棧的第二層,從 Running 狀態(tài)轉(zhuǎn)到 Paused 狀態(tài)。

activity的棧式管理

舉個(gè)栗子,我們吃冰糖葫蘆的時(shí)候,都是從最上面的一顆開始吃,只有當(dāng)最上面的那顆吃完了,我們這才會(huì)開始吃下面的一顆,所以我們正在吃的,永遠(yuǎn)是最上面的那顆。(ˇ?ˇ) ~

六、Activity的啟動(dòng)模式

活動(dòng)的啟動(dòng)模式對(duì)你來說應(yīng)該是個(gè)全新的概念,在實(shí)際項(xiàng)目中我們應(yīng)該根據(jù)特定的需求為每個(gè)活動(dòng)指定恰當(dāng)?shù)膯?dòng)模式。啟動(dòng)模式一共有四種,分別是 standardsingleTopsingleTasksingleInstance,可以在 AndroidManifest.xml 中通 過給<activity> 標(biāo)簽 指android:launchMode屬性來選擇啟動(dòng)模式。下面我們來逐個(gè)進(jìn)行學(xué)習(xí)。

1.standard
standard 是活動(dòng)默認(rèn)的啟動(dòng)模式,在不進(jìn)行顯式指定的情況下,所有活動(dòng)都會(huì)自動(dòng)使用這種啟動(dòng)模式。經(jīng)過上面的學(xué)習(xí),你已經(jīng)知道了 Android 是使用返回棧來管理活動(dòng)的,在 standard 模式(即默認(rèn)情況)下,每當(dāng)啟動(dòng)一個(gè)新的活動(dòng),它就會(huì)在返回棧中入棧,并處于棧頂?shù)奈恢谩?duì)于使用standard 模式的活動(dòng),系統(tǒng)不會(huì)在乎這個(gè)活動(dòng)是否已經(jīng)在返回棧中存在,每次啟動(dòng)都會(huì)創(chuàng)建該活動(dòng)的一個(gè)新的實(shí)例。

2.singleTop
singleTop也是發(fā)送新的實(shí)例,但不同standard的一點(diǎn)是,在請(qǐng)求的Activity正好位于棧頂時(shí)(配置成singleTop的Activity),不會(huì)構(gòu)造新的實(shí)例

<activity
    android:name=".MainActivity"
    android:launchMode="singleTop">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

3.singleTask
活動(dòng)在整個(gè)應(yīng)用程序的上下文中只存在一個(gè)實(shí)例,每次啟動(dòng)該活動(dòng)時(shí)系統(tǒng)首先會(huì)在返回棧中檢查是否存在該活動(dòng)的實(shí)例,如果發(fā)現(xiàn)已經(jīng)存在則直接使用該實(shí)例,并把在這個(gè)活動(dòng)之上的所有活動(dòng)統(tǒng)統(tǒng)出棧,如果沒有發(fā)現(xiàn)就會(huì)創(chuàng)建一個(gè)新的活動(dòng)實(shí)例。

<activity
    android:name=".MainActivity"
    android:launchMode="singleTask">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

4.singleInstance
singleInstance模式應(yīng)該算是四種啟動(dòng)模式中最特殊也最復(fù)雜的一個(gè)了,你也需要多花點(diǎn)功夫來理解這個(gè)模式。不同于以上三種啟動(dòng)模式,指定為 singleInstance模式的活動(dòng)會(huì)啟用一個(gè)新的返回棧來管理這個(gè)活動(dòng),這個(gè)模式主要解決了在不同app之間的共享活動(dòng)實(shí)例的問題
網(wǎng)上找了個(gè)栗子,如果開啟一個(gè)導(dǎo)游服務(wù)類的應(yīng)用程序,里面有個(gè)Activity是開啟GOOGLE地圖的,當(dāng)按下home鍵退回到主菜單又啟動(dòng)GOOGLE地圖的應(yīng)用時(shí),顯示的就是剛才的地圖,實(shí)際上是同一個(gè)Activity,實(shí)際上這就引入了singleInstance。singleInstance模式就是將該Activity單獨(dú)放入一個(gè)棧中,這樣這個(gè)棧中只有這一個(gè)Activity,不同應(yīng)用的intent都由這個(gè)Activity接收和展示,這樣就做到了共享。當(dāng)然前提是這些應(yīng)用都沒有被銷毀,所以剛才是按下的HOME鍵,如果按下了返回鍵,則無效。

<activity
    android:name=".MainActivity"
    android:launchMode="singleInstance">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

七、Activity使用小技巧

你已經(jīng)掌握了關(guān)于活動(dòng)非常多的知識(shí),但運(yùn)用的技巧卻是多種多樣。所以,在這里我準(zhǔn)備教你幾種關(guān)于活動(dòng)的最佳實(shí)踐技巧,這些技巧在你以后的開發(fā)工作當(dāng)中將會(huì)非常受用。

知曉當(dāng)前是在哪一個(gè)活動(dòng)
這個(gè)技巧將教會(huì)你,如何根據(jù)程序當(dāng)前的界面就能判斷出這是哪一個(gè)活動(dòng)。
因?yàn)樵谖覀冋嬲M(jìn)入企業(yè)后,可能會(huì)接手別人寫的代碼。閱讀別人的代碼時(shí)有一個(gè)很頭疼的問題,就是你需要在某個(gè)界面上修改一些非常簡(jiǎn)單的東西,但是你半天找不到這個(gè)界面對(duì)應(yīng)的活動(dòng)是哪一個(gè)。
我們還是在上面的Demo的基礎(chǔ)上修改。首先需要新建一個(gè) BaseActivity 繼承自AppCompatActivity,然后在 BaseActivity 中重寫 onCreate()方法,如下所示:

public class BaseActivity extends AppCompatActivity {
    @Override
    public void onCreate(Bundle savedInstanceState, PersistableBundle persistentState) {
        super.onCreate(savedInstanceState, persistentState);
        Log.d("BaseActivity", getClass().getSimpleName());
    }
}

接下來我們需要讓 BaseActivity 成為 Demo項(xiàng)目中所有活動(dòng)的父類。修改MainActivity、SecondActivity 和 ThirdActivity 的繼承結(jié)構(gòu),讓它們不再繼承自 AppCompatActivity,而是繼承自 BaseActivity。
這樣每當(dāng)我們進(jìn)入到一個(gè)活動(dòng)的界面,該活動(dòng)的類名就會(huì)被打印出來,這樣我們就可以時(shí)時(shí)刻刻知曉當(dāng)前界面對(duì)應(yīng)的是哪一個(gè)活動(dòng)了。

隨時(shí)隨地退出程序
如果目前你手機(jī)的界面還停留在 ThirdActivity,你會(huì)發(fā)現(xiàn)當(dāng)前想退出程序是非常不方便的,需要連按三次 Back 鍵才行,如果我們的程序需要一個(gè)注銷或者退出的功能該怎么辦呢?必須要有一個(gè)隨時(shí)隨地都能退出程序的方案才行。

其實(shí)解決思路也很簡(jiǎn)單,只需要用一個(gè)專門的集合類對(duì)所有的活動(dòng)進(jìn)行管理就可以了,
下面我們就來實(shí)現(xiàn)一下。

public class ActivityCollector {
    public static List<AppCompatActivity> activities = new ArrayList<>();

    /**
     *  添加
     */
    public static void addActivity(AppCompatActivity activity) {
        activities.add(activity);
    }

    /**
     * 移除
     */
    public static void removeActivity(AppCompatActivity activity) {
        activities.remove(activity);
    }

    /**
     * 結(jié)束所有
     */
    public static void finishAll() {
        for (AppCompatActivity activity : activities) {
            if (!activity.isFinishing()) {
                activity.finish();
            }
        }
    }
}

在活動(dòng)管理器中,我們通過一個(gè) List 來暫存活動(dòng),然后提供了一個(gè)addActivity()方法用于向 List 中添加一個(gè)活動(dòng),提供了一個(gè) removeActivity()方法用于從 List 中移除活動(dòng),最后提供了一個(gè) finishAll()方法用于將 List 中存儲(chǔ)的活動(dòng)全部都銷毀掉。

接下來修改 BaseActivity 中的代碼,如下所示:

public class BaseActivity extends AppCompatActivity {
    @Override
    public void onCreate(Bundle savedInstanceState, PersistableBundle persistentState) {
        super.onCreate(savedInstanceState, persistentState);
        Log.d("BaseActivity", getClass().getSimpleName());
        ActivityCollector.addActivity(this);
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        ActivityCollector.removeActivity(this);
    }
}

在 BaseActivity 的 onCreate()方法中調(diào)用了 ActivityCollector 的addActivity()方法,表明將當(dāng)前正在創(chuàng)建的活動(dòng)添加到活動(dòng)管理器里。然后在 BaseActivity 中重寫 onDestroy()方法,并調(diào)用了 ActivityCollector 的 removeActivity()方法,表明將一個(gè)馬上要銷毀的活動(dòng)從活動(dòng)管理器里移除。

以后不管在什么地方想要退出應(yīng)用,都可以調(diào)用如下代碼

ActivityCollector.finishAll();

當(dāng)然你還可以在銷毀所有活動(dòng)的代碼后面再加上殺掉當(dāng)前進(jìn)程的代碼,以保證程序完全退出。

啟動(dòng)活動(dòng)的最佳寫法
啟動(dòng)活動(dòng)的方法相信你已經(jīng)非常熟悉了,首先通過 Intent 構(gòu)建出當(dāng)前的“意圖”,然后調(diào)用 startActivity()或 startActivityForResult()方法將活動(dòng)啟動(dòng)起來,如果有數(shù)據(jù)需要從一個(gè)活動(dòng)傳遞到另一個(gè)活動(dòng),也可以借助 Intent 來完成。

假設(shè) SecondActivity 中需要用到兩個(gè)非常重要的字符串參數(shù),在啟動(dòng) SecondActivity 的
時(shí)候必須要傳遞過來,那么我們很容易會(huì)寫出如下代碼:

Intent intent = new Intent(MainActivity.this, SecondActivity.class);
intent.putExtra("param1", "data1");
intent.putExtra("param2", "data2");
startActivity(intent);

這樣寫是完全正確的,但如果SecondActivity不是你自己寫的,而你也不知道需要傳遞哪些數(shù)據(jù),那就尷尬了。
但如果在SecondActivity里有這樣一個(gè)方法

public static void actionStart(Context context, String data1, String data2) {
Intent intent = new Intent(context, SecondActivity.class);
intent.putExtra("param1", data1);
intent.putExtra("param2", data2);
context.startActivity(intent);
}

是不是瞬間就一目了然了,你可以非常清晰地知道啟動(dòng) SecondActivity 需要傳遞哪些數(shù)據(jù)。另外,這樣寫還簡(jiǎn)化了啟動(dòng)活動(dòng)的代碼,現(xiàn)在只需要一行代碼就可以啟動(dòng) SecondActivity

SecondActivity.actionStart(FirstActivity.this, "data1", "data2");

我也是剛接觸android沒多久,如發(fā)現(xiàn)有錯(cuò)誤或者什么好的建議,歡迎指正!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,182評(píng)論 6 543
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,489評(píng)論 3 429
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,290評(píng)論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,776評(píng)論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,510評(píng)論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,866評(píng)論 1 328
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,860評(píng)論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 43,036評(píng)論 0 290
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,585評(píng)論 1 336
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,331評(píng)論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,536評(píng)論 1 374
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,058評(píng)論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,754評(píng)論 3 349
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,154評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,469評(píng)論 1 295
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,273評(píng)論 3 399
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,505評(píng)論 2 379

推薦閱讀更多精彩內(nèi)容