當(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
然后會出現(xiàn)這個(gè)界面值依,取個(gè)名字就可以點(diǎn)OK了
會出現(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中注冊碟案,打開app -> manifests -> AndroidManifests
加入下圖中圈出的代碼
由于最外層的<manifest>標(biāo)簽中已經(jīng)通過 package 屬性指定了程序的包名是
com.example.administrator愿险,因此在注冊活動(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īng)典的圖了
這張圖當(dāng)年在我剛接觸android的時(shí)候可是給了我一段很痛苦的回憶瞧省,簡單的來說就是看不懂扯夭,所以我就用小白一點(diǎn)的語言來總結(jié)一下吧。
首先鞍匾,我們可以把a(bǔ)ctivity看成是一個(gè)人交洗,人都有出生到死亡的過程,activity也是有這個(gè)過程橡淑,而人在特定的時(shí)間會干一些特定的事构拳,比如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)會停止動(dòng)畫等消耗CPU的事情。從上文的描述已經(jīng)知道啰脚,應(yīng)該在這里保存你的一些數(shù)據(jù),因?yàn)檫@個(gè)時(shí)候你的程序的優(yōu)先級降 低殷蛇,有可能被系統(tǒng)收回。在這里保存的數(shù)據(jù)拣播,應(yīng)該在onResume里讀出來晾咪。
5.onStop() -- 停止時(shí)
變得不可見 ,被下一個(gè)activity覆蓋了
6.onDestroy() -- 銷毀時(shí)
這里主要是做一些釋放資源的操作贮配。
四谍倦、Activity之間的通信
在一個(gè)項(xiàng)目中,我們會用到很多的activity泪勒,因此我們需要一種特別的機(jī)制幫助我們在 Activity 之間傳遞消息昼蛀。
Intent的使用
Intent是一種消息傳遞的機(jī)制,它負(fù)責(zé)對操作的動(dòng)作圆存、動(dòng)作涉及數(shù)據(jù)叼旋、附加數(shù)據(jù)進(jìn)行描述,Android則根據(jù)此Intent的描述沦辙,負(fù)責(zé)找到對應(yīng)的組件夫植,將 Intent傳遞給調(diào)用的組件,并完成組件的調(diào)用油讯。
我們有兩種形式來使用Intent:
1.使用顯式Intent
通過指定具體的組件類详民,通知應(yīng)用啟動(dòng)對應(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)呢心肪?簡單來說就是可以響應(yīng)我們這個(gè)隱式 Intent的活動(dòng),那么目前activity 可以響應(yīng)什么樣的隱式 Intent 呢杀狡?額蒙畴,現(xiàn)在好像還什么都響應(yīng)不了贰镣,不過很快就會有了呜象。
我們還是要從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í)候會自動(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 對象,再調(diào)用 Intent的 setData()方法將這個(gè) Uri 對象傳遞進(jìn)去糙麦。
與此對應(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)簽中都不會指定過多的內(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ù)。通過查閱文檔你會發(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ù)是請求碼戚揭,用于在之后的回調(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被銷毀之后會回調(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钝凶,即我們在啟動(dòng)活動(dòng)時(shí)傳入的請求碼仪芒。
第二個(gè)參數(shù) resultCode,即我們在返回?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ù)都會回調(diào)到 onActivityResult()這個(gè)方法中饺蔑,因此我們首先要做的就是通過檢查 requestCode 的值來判斷數(shù)據(jù)來源。確定數(shù)據(jù)是從SecondActivity 返回的之后嗜诀,我們再通過 resultCode 的值來判斷處理結(jié)果是否成功猾警。最后從data中取值并打印出來,這樣就完成了向上一個(gè)活動(dòng)返回?cái)?shù)據(jù)的工作隆敢。
五发皿、Activity的棧式管理
Android針對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)最上面的那顆吃完了永票,我們這才會開始吃下面的一顆,所以我們正在吃的滥沫,永遠(yuǎn)是最上面的那顆侣集。(ˇ?ˇ) ~
六、Activity的啟動(dòng)模式
活動(dòng)的啟動(dòng)模式對你來說應(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)都會自動(dòng)使用這種啟動(dòng)模式荣恐。經(jīng)過上面的學(xué)習(xí),你已經(jīng)知道了 Android 是使用返回棧來管理活動(dòng)的累贤,在 standard 模式(即默認(rèn)情況)下叠穆,每當(dāng)啟動(dòng)一個(gè)新的活動(dòng),它就會在返回棧中入棧臼膏,并處于棧頂?shù)奈恢门鸨弧τ谑褂胹tandard 模式的活動(dòng),系統(tǒng)不會在乎這個(gè)活動(dòng)是否已經(jīng)在返回棧中存在讶请,每次啟動(dòng)都會創(chuàng)建該活動(dòng)的一個(gè)新的實(shí)例祷嘶。
2.singleTop
singleTop也是發(fā)送新的實(shí)例,但不同standard的一點(diǎn)是夺溢,在請求的Activity正好位于棧頂時(shí)(配置成singleTop的Activity)论巍,不會構(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)首先會在返回棧中檢查是否存在該活動(dòng)的實(shí)例风响,如果發(fā)現(xiàn)已經(jīng)存在則直接使用該實(shí)例嘉汰,并把在這個(gè)活動(dòng)之上的所有活動(dòng)統(tǒng)統(tǒng)出棧,如果沒有發(fā)現(xiàn)就會創(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)會啟用一個(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)非常多的知識归榕,但運(yùn)用的技巧卻是多種多樣。所以吱涉,在這里我準(zhǔn)備教你幾種關(guān)于活動(dòng)的最佳實(shí)踐技巧刹泄,這些技巧在你以后的開發(fā)工作當(dāng)中將會非常受用。
知曉當(dāng)前是在哪一個(gè)活動(dòng)
這個(gè)技巧將教會你怎爵,如何根據(jù)程序當(dāng)前的界面就能判斷出這是哪一個(gè)活動(dòng)特石。
因?yàn)樵谖覀冋嬲M(jìn)入企業(yè)后,可能會接手別人寫的代碼鳖链。閱讀別人的代碼時(shí)有一個(gè)很頭疼的問題姆蘸,就是你需要在某個(gè)界面上修改一些非常簡單的東西,但是你半天找不到這個(gè)界面對應(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)的類名就會被打印出來皮壁,這樣我們就可以時(shí)時(shí)刻刻知曉當(dāng)前界面對應(yīng)的是哪一個(gè)活動(dòng)了椭更。
隨時(shí)隨地退出程序
如果目前你手機(jī)的界面還停留在 ThirdActivity,你會發(fā)現(xiàn)當(dāng)前想退出程序是非常不方便的蛾魄,需要連按三次 Back 鍵才行,如果我們的程序需要一個(gè)注銷或者退出的功能該怎么辦呢甜孤?必須要有一個(gè)隨時(shí)隨地都能退出程序的方案才行。
其實(shí)解決思路也很簡單畏腕,只需要用一個(gè)專門的集合類對所有的活動(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 中存儲的活動(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í)候必須要傳遞過來,那么我們很容易會寫出如下代碼:
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ù)泛啸。另外,這樣寫還簡化了啟動(dòng)活動(dòng)的代碼,現(xiàn)在只需要一行代碼就可以啟動(dòng) SecondActivity
SecondActivity.actionStart(FirstActivity.this, "data1", "data2");
我也是剛接觸android沒多久候址,如發(fā)現(xiàn)有錯(cuò)誤或者什么好的建議吕粹,歡迎指正!