當(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
按照上面兩張圖一步步做就可以了,新手們最好選擇Empty Activity(空活動(dòng))
手動(dòng)創(chuàng)建activity
第一步
先建一個(gè)class,包名處右擊鼠標(biāo),選擇New -> Java Class
然后會(huì)出現(xiàn)這個(gè)界面,取個(gè)名字就可以點(diǎn)OK了
會(huì)出現(xiàn)這個(gè)界面
第二步
在layout里New一個(gè)layout resource file
出現(xiàn)這個(gè)界面,取個(gè)名字點(diǎn)擊OK
然后我們的layout就建好了
第三步
將建好的layout添加到class中
1.繼承AppCompatActivity(以前是直接繼承Activity,兩者用法差別不大)
2.重寫OnCreate方法
3.設(shè)置layout
第四步
在AndroidManifest中注冊(cè),打開app -> manifests -> AndroidManifests
加入下圖中圈出的代碼
由于最外層的<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)典的圖了
這張圖當(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)容。
- android:scheme
用于指定數(shù)據(jù)的協(xié)議部分,如上例中的 http 部分。 - android:host
用于指定數(shù)據(jù)的主機(jī)名部分,如上例中的 www.baidu.com部分。 - android:port
用于指定數(shù)據(jù)的端口部分,一般緊隨在主機(jī)名之后。 - android:path
用于指定主機(jī)名和端口之后的部分,如一段網(wǎng)址中跟在域名之后的內(nèi)容。 - 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_OK或RESULT_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)。
舉個(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)模式一共有四種,分別是 standard、singleTop、singleTask和singleInstance,可以在 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ò)誤或者什么好的建議,歡迎指正!