本文目錄結(jié)構(gòu):
一寺酪、活動(dòng)的生命周期
二输涕、活動(dòng)的啟動(dòng)模式
三盐数、活動(dòng)間的信息傳遞之一 —— Intent
一埂淮、活動(dòng)的生命周期
1.返回棧
Android是使用任務(wù)(Task)來管理活動(dòng)的姑隅,一個(gè)任務(wù)就是一組存放在棧里的活動(dòng)的集合,這個(gè)棧也叫返回棧倔撞。在默認(rèn)情況下讲仰,當(dāng)我們啟動(dòng)了一個(gè)活動(dòng),那么它會(huì)入棧误窖,并處于棧頂?shù)奈恢枚E獭.?dāng)我們按下返回鍵或者調(diào)用finish方法時(shí),處于棧頂?shù)幕顒?dòng)就會(huì)出棧霹俺。系統(tǒng)總是顯示處于棧頂?shù)幕顒?dòng)柔吼。
2.活動(dòng)狀態(tài)
活動(dòng)的狀態(tài)可以分為4種:
(1)運(yùn)行狀態(tài)
當(dāng)一個(gè)活動(dòng)處于棧頂?shù)臅r(shí)候,那么它就處于運(yùn)行狀態(tài)丙唧。系統(tǒng)就不愿意就是回收運(yùn)行狀態(tài)的活動(dòng)愈魏,因?yàn)檫@會(huì)給用戶帶來很不好的體驗(yàn)。
(2)暫停狀態(tài)
當(dāng)一個(gè)活動(dòng)不處于棧頂?shù)匀豢梢姇r(shí)想际,它就處于暫停狀態(tài)培漏。比如對(duì)話框形式的活動(dòng)只會(huì)占用屏幕中間的區(qū)域。系統(tǒng)也不愿意回收這樣的活動(dòng)胡本,只有在內(nèi)存極低的時(shí)候才會(huì)考慮去回收牌柄。
(3)停止?fàn)顟B(tài)
當(dāng)一個(gè)活動(dòng)不再處于棧頂,并且不可見的時(shí)候侧甫,就進(jìn)入了停止?fàn)顟B(tài)珊佣。系統(tǒng)仍然會(huì)為這種活動(dòng)保存相應(yīng)的狀態(tài)和成員變量,但這并不是完全可靠的披粟。當(dāng)其他地方需要內(nèi)存咒锻,系統(tǒng)就有可能回收掉該活動(dòng)。
(4)銷毀狀態(tài)
當(dāng)一個(gè)活動(dòng)被棧移除之后守屉,它就處于銷毀狀態(tài)惑艇。系統(tǒng)最愿意回收這樣的活動(dòng),從而保持手機(jī)內(nèi)存的充足拇泛。
3.活動(dòng)的生命周期
(1)onCreate
它會(huì)在活動(dòng)第一次創(chuàng)建的時(shí)候被調(diào)用滨巴。我們應(yīng)該在該方法中完成活動(dòng)的初始化操作,比如加載布局俺叭、綁定事件等恭取。
(2)onStart
該方法在活動(dòng)由不可見變?yōu)榭梢姷臅r(shí)候調(diào)用。
(3)onResume
該方法在活動(dòng)準(zhǔn)備好和用戶交互的時(shí)候調(diào)用绪颖。此時(shí)的活動(dòng)一定處于棧頂?shù)奈恢谩?br>
(4)onPause
該方法在系統(tǒng)準(zhǔn)備去啟動(dòng)或恢復(fù)另一個(gè)活動(dòng)的時(shí)候調(diào)用秽荤。我們通常會(huì)在這個(gè)方法中將一些消耗CPU的資源釋放掉甜奄,但該方法的執(zhí)行速度一定要快,不然會(huì)影響到新的棧頂活動(dòng)的調(diào)用窃款。
(5)onStop
該方法在活動(dòng)完全不可見的時(shí)候調(diào)用课兄。它和onPause方法不同的是,如果啟動(dòng)的新活動(dòng)是一個(gè)對(duì)話框形式的活動(dòng)晨继,那么onPause方法會(huì)被調(diào)用烟阐,而它不會(huì)。
(6)onDestroy
該方法會(huì)在活動(dòng)被銷毀之前調(diào)用紊扬。
(7)onRestart
該方法會(huì)在活動(dòng)從停止?fàn)顟B(tài)變?yōu)檫\(yùn)行狀態(tài)之前調(diào)用蜒茄。
PS:如果活動(dòng)被銷毀了,但是可能存在臨時(shí)數(shù)據(jù)和狀態(tài)餐屎,那要怎么辦呢檀葛?
①可以調(diào)用onSaveInstanceState方法將數(shù)據(jù)臨時(shí)保存起來
@Override
protected void onSaveInstanceState(Bundle outState){
super.onSaveInstanceState(outState);
String data = "Keep it";
outState.putString("tempData",data);
}
②然后在onCreate方法中判斷savedInstanceState是否為空
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
......
if(savedInstanceState != null)
String tempData = savedInstanceState.getString("tempData");
}
二、活動(dòng)的啟動(dòng)模式
活動(dòng)的啟動(dòng)模式一共有4種腹缩,它們需要在AndroidManifest文件中通過給<activity>標(biāo)簽指定android:launchMode屬性來設(shè)置屿聋。
1.standard
它是活動(dòng)默認(rèn)的啟動(dòng)模式。每當(dāng)有一個(gè)活動(dòng)啟動(dòng)時(shí)藏鹊,它就會(huì)入棧并處于棧頂?shù)奈恢萌蠹ァO到y(tǒng)根本不在乎棧里是否已經(jīng)有了該活動(dòng)的實(shí)例,每次啟動(dòng)活動(dòng)都會(huì)創(chuàng)建一個(gè)新的實(shí)例盘寡。
2.singleTop
當(dāng)活動(dòng)指定為該模式時(shí)楚殿,在啟動(dòng)活動(dòng)時(shí)如果發(fā)現(xiàn)棧頂?shù)幕顒?dòng)已經(jīng)是該活動(dòng),則系統(tǒng)會(huì)直接使用它竿痰,不會(huì)再創(chuàng)建新的活動(dòng)實(shí)例脆粥。但如果該活動(dòng)不在棧頂時(shí)再啟動(dòng)該活動(dòng)時(shí),還是會(huì)創(chuàng)建新的實(shí)例的菇曲。
3.singleTask
當(dāng)活動(dòng)處于該模式時(shí)冠绢,每次啟動(dòng)活動(dòng)時(shí)系統(tǒng)首先會(huì)在棧里檢查是否存在該活動(dòng)的實(shí)例抚吠,如果發(fā)現(xiàn)有則直接使用常潮,并把在該活動(dòng)之上的所有活動(dòng)出棧。如果沒發(fā)現(xiàn)則創(chuàng)建一個(gè)新的活動(dòng)實(shí)例楷力。
4.singleInstance
當(dāng)活動(dòng)處于該模式時(shí)喊式,系統(tǒng)會(huì)啟用一個(gè)新的棧來管理這個(gè)活動(dòng)。它可以解決共享活動(dòng)實(shí)例的問題萧朝。比如:活動(dòng)B為該模式岔留,然后A啟動(dòng)B,B啟動(dòng)C检柬,那么第一次按下返回鍵時(shí)系統(tǒng)會(huì)回到A献联,再按下一次時(shí)會(huì)回到B,再按下一次則退出應(yīng)用。一個(gè)棧里的活動(dòng)沒有了之后才會(huì)去到另一個(gè)棧里逆。
三进胯、活動(dòng)間的信息傳遞之一 —— Intent
1.顯式Intent
(1)構(gòu)造方法
//Intent intent = new Intent(Context packageContext,Class<?> cls);
//前者為啟動(dòng)活動(dòng)的上下文,后者為想要啟動(dòng)的目標(biāo)活動(dòng)
Intent intent = new Intent(FirstActivity.this,SecondActivity.class);
(2)setComponent方法
ComponentName componentName = new ComponentName(this, SecondActivity.class);
Intent intent = new Intent();
intent.setComponent(componentName);
startActivity(intent);
(3)setClass/setClassName方法
Intent intent = new Intent();
intent.setClass(this, SecondActivity.class);
// 或者intent.setClassName(this, "top.longsh1z.www.SecondActivity");
// 或者intent.setClassName(this.getPackageName(), "top.longsh1z.www.SecondActivity");
startActivity(intent);
2.隱式Intent
顧名思義原押,隱式Intent不會(huì)明確的指出想要啟動(dòng)的activity胁镐,而是通過指定action和category等信息讓系統(tǒng)來選擇要啟動(dòng)的活動(dòng)。
首先诸衔,在AndroidManifest文件中盯漂,目標(biāo)活動(dòng)要有<intent-filter>標(biāo)簽,里面包含<action><category>子標(biāo)簽笨农,只有這兩個(gè)子標(biāo)簽中的內(nèi)容同時(shí)匹配才能夠生效就缆。比如:
<activity android:name=".ui.Main2Activity">
<intent-filter>
<action android:name="top.longsh1z.www.Main2Activity"/>
<!--該category是一種默認(rèn)的category-->
<!--在調(diào)用startActivity方法時(shí)會(huì)自動(dòng)將這個(gè)category加到intent中-->
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
設(shè)置intent有兩種方法:
(1)構(gòu)造方法
Intent intent = new Intent("top.longsh1z.www.Main2Activity");
//如果category不是默認(rèn)的話要再加下面的一條語句
//比如在AndroidManifest中自定義的category為
//top.longsh1z.www.Main2Activity_category,那么該語句為
//intent.addCategory("top.longsh1z.www.Main2Activity_category");
startActivity(intent);
(2)setAction方法
Intent intent = new Intent();
intent.setAction("top.longsh1z.www.Main2Activity");
//如果category不是默認(rèn)的話同上
startActivity(intent);
3.更多隱式Intent的用法
我們也可以調(diào)用系統(tǒng)中固有的活動(dòng)谒亦,比如系統(tǒng)的瀏覽器违崇,撥號(hào)等等。比如調(diào)用系統(tǒng)瀏覽器:
//Intent.ACTION_VIEW是系統(tǒng)內(nèi)置的動(dòng)作诊霹,其常量值為android.intent.action.VIEW
Intent intent = new Intent(Intent.ACTION_VIEW);
//這條語句的意思是打開百度羞延,具體其他用法請(qǐng)自己搜索
intent.setData(Uri.parse("https://www.baidu.com"));
startActivity(intent);
另外,在一個(gè)活動(dòng)的<action>標(biāo)簽里也可以寫成系統(tǒng)內(nèi)置的動(dòng)作脾还。當(dāng)然這個(gè)前提是你的程序要有這樣的功能伴箩,不然的話就會(huì)報(bào)錯(cuò)。
4.向下一個(gè)活動(dòng)傳遞數(shù)據(jù)
使用intent.putExtra方法放消息鄙漏,使用intent.getStringExtra方法拿消息嗤谚。
//放消息進(jìn)intent中
String data = "Hello world!";
Intent intent = new Intent(FirstActivity.this,SecondActivity.class);
intent.putExtra("MyData",data);
//其中data不一定只限于字符串,也可以為int,boolean類型
startActivity(intent);
//取消息
Intent intent = getIntent();
String data = intent.getStringExtra("MyData");
//若傳遞的數(shù)據(jù)為其他類型怔蚌,則為getXxxExtra方法巩步,比如getIntExtra,getBooleanExtra方法
5.返回?cái)?shù)據(jù)給上一個(gè)活動(dòng)
總體思路為(這里假設(shè)是FActivity<簡(jiǎn)寫為F>)跳到SActivity<簡(jiǎn)寫為S>,再S返回?cái)?shù)據(jù)給F)
先在F中使用startActivityForResult方法向S傳遞一個(gè)唯一的請(qǐng)求碼桦踊,
然后在S中使用setResult方法將結(jié)果碼和數(shù)據(jù)返回給F椅野,
最后F在onActivityResult中通過請(qǐng)求碼和結(jié)果碼拿到返回的數(shù)據(jù)。
//F中:
Intent intent = new Intent(F.this,S.class);
startActivityForResult(intent,1);//這里請(qǐng)求碼為1
//S中:
Intent intent = new Intent();
intent.putExtra("dataReturn","I am dataReturn.");
setResult(RESULT_OK,intent);
//第一個(gè)參數(shù)一般只使用RESULT_OK或RESULT_CANCELED這兩個(gè)值
//F中:
@Override
protected void onActivityResult(int requestCode,int resultCode,Intent data){
//第一個(gè)參數(shù)為請(qǐng)求碼籍胯,是為了區(qū)分是哪個(gè)activity返回的數(shù)據(jù)竟闪,即數(shù)據(jù)來源
//第二個(gè)參數(shù)是判斷處理結(jié)果是否成功
//第三個(gè)參數(shù)就是返回的數(shù)據(jù)
switch(requestCode){
case 1:
if(resultCode == RESULT_OK){
String data = intent.getStringExtra("dataReturn");
}
break;
}
}