生命周期
官網(wǎng)上的生命周期圖:
- onCreate: Activity正在創(chuàng)建,生命周期的第一個(gè)方法。在此方法中做一些初始化工作(setContentView加載界面布局,加載基本數(shù)據(jù))
- onStart: Activity 正在啟動(dòng)页徐,已經(jīng)可見(jiàn),但在后臺(tái)(沒(méi)有獲得焦點(diǎn))
- onResume: Activity獲得焦點(diǎn)出現(xiàn)在前臺(tái)可以交互
- onPause: Activity 正在停止银萍,可做一些數(shù)據(jù)存儲(chǔ)变勇,停止動(dòng)畫(huà)...
- onStop: Activity 停止,不可見(jiàn)
- onDestory: Activity 銷毀贴唇,進(jìn)行資源回收
基本函數(shù)
public void onCreate(Bundle savedInstanceState);
public void onStart();
public void onRestart();
public void onActivityResult(int requestCode, int resultCode, Intent data);
public void onResume();
public void onPause();
public void onStop();
public void onDestroy();
public void attach(Activity proxyActivity, DLPluginPackage pluginPackage);
public void onSaveInstanceState(Bundle outState);
public void onNewIntent(Intent intent);
public void onRestoreInstanceState(Bundle savedInstanceState);
public boolean onTouchEvent(MotionEvent event);
public boolean onKeyUp(int keyCode, KeyEvent event);
public void onWindowAttributesChanged(LayoutParams params);
public void onWindowFocusChanged(boolean hasFocus);
public void onBackPressed();
public boolean onCreateOptionsMenu(Menu menu);
public boolean onOptionsItemSelected(MenuItem item);
- onRestart:Activity 正在重現(xiàn)啟動(dòng)搀绣,是當(dāng)前Activity從不可見(jiàn)到可見(jiàn)狀態(tài)會(huì)觸發(fā)
- onActivityResult: 在Activity中得到新打開(kāi)Activity關(guān)閉后返回的數(shù)據(jù)
特殊情況下觸發(fā)(橫豎屏切換,資源不足被殺)
- onSaveInstanceState:Activity被銷毀戳气,調(diào)用此方法保存當(dāng)前狀態(tài)链患,在onStop之前調(diào)用
- onRestoreInstanceState:Activity 被重啟調(diào)用,通過(guò)Bundle傳遞保存的數(shù)據(jù)瓶您,在onStart 之后調(diào)用
- onNewIntent
- onTouchEvent 觸摸屏幕時(shí)調(diào)用麻捻,可以獲取手勢(shì)的位置
- onKeyUp 鍵盤(pán)事件,點(diǎn)擊來(lái)手機(jī)按鍵
- onWindowAttributesChanged
- onWindowFocusChanged
- onBackPressed 返回鍵點(diǎn)擊
- onCreateOptionsMenu 加載菜單布局
- onOptionsItemSelected 響應(yīng)菜單選項(xiàng)
對(duì)話框模式
<activity
android:name=".TAccountActivity"
android:theme="@android:style/Theme.Translucent"
android:configChanges="fontScale|orientation|keyboardHidden|locale|navigation|screenSize|uiMode"
android:screenOrientation="portrait"
/>
布局文件設(shè)置在父布局的中間览闰,動(dòng)態(tài)添加一個(gè)fragment
<FrameLayout
android:id="@+id/account_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
/>
啟動(dòng)模式
Standared(默認(rèn)):standard是默認(rèn)的啟動(dòng)模式芯肤,即如果不指定launchMode屬性,則自動(dòng)就會(huì)使用這種啟動(dòng)模式压鉴。這種啟動(dòng)模式表示每次啟動(dòng)該Activity時(shí)系統(tǒng)都會(huì)為創(chuàng)建一個(gè)新的實(shí)例崖咨,并且總會(huì)把它放入到當(dāng)前的任務(wù)當(dāng)中。聲明成這種啟動(dòng)模式的Activity可以被實(shí)例化多次油吭,一個(gè)任務(wù)當(dāng)中也可以包含多個(gè)這種Activity的實(shí)例待榔。
SingleTop:這種啟動(dòng)模式表示嘲碧,如果要啟動(dòng)的這個(gè)Activity在當(dāng)前任務(wù)中已經(jīng)存在了,并且還處于棧頂?shù)奈恢茫敲聪到y(tǒng)就不會(huì)再去創(chuàng)建一個(gè)該Activity的實(shí)例锈玉,而是調(diào)用棧頂Activity的onNewIntent()方法。聲明成這種啟動(dòng)模式的Activity也可以被實(shí)例化多次身辨,一個(gè)任務(wù)當(dāng)中也可以包含多個(gè)這種Activity的實(shí)例障簿。
舉個(gè)例子來(lái)講,一個(gè)任務(wù)的返回棧中有A、B痕惋、C区宇、D四個(gè)Activity,其中A在最底端值戳,D在最頂端议谷。這個(gè)時(shí)候如果我們要求再啟動(dòng)一次D,并且D的啟動(dòng)模式是"standard"堕虹,那么系統(tǒng)就會(huì)再創(chuàng)建一個(gè)D的實(shí)例放入到返回棧中卧晓,此時(shí)棧內(nèi)元素為:A-B-C-D-D。而如果D的啟動(dòng)模式是"singleTop"的話赴捞,由于D已經(jīng)是在棧頂了逼裆,那么系統(tǒng)就不會(huì)再創(chuàng)建一個(gè)D的實(shí)例,而是直接調(diào)用D Activity的onNewIntent()方法赦政,此時(shí)棧內(nèi)元素仍然為:A-B-C-D波附。SingleTask:這種啟動(dòng)模式表示,系統(tǒng)會(huì)創(chuàng)建一個(gè)新的任務(wù)昼钻,并將啟動(dòng)的Activity放入這個(gè)新任務(wù)的棧底位置掸屡。但是,如果現(xiàn)有任務(wù)當(dāng)中已經(jīng)存在一個(gè)該Activity的實(shí)例了然评,那么系統(tǒng)就不會(huì)再創(chuàng)建一次它的實(shí)例仅财,而是會(huì)直接調(diào)用它的onNewIntent()方法。聲明成這種啟動(dòng)模式的Activity碗淌,在同一個(gè)任務(wù)當(dāng)中只會(huì)存在一個(gè)實(shí)例盏求。注意這里我們所說(shuō)的啟動(dòng)Activity,都指的是啟動(dòng)其它應(yīng)用程序中的Activity亿眠,因?yàn)?singleTask"模式在默認(rèn)情況下只有啟動(dòng)其它程序的Activity才會(huì)創(chuàng)建一個(gè)新的任務(wù)碎罚,啟動(dòng)自己程序中的Activity還是會(huì)使用相同的任務(wù)
SingleInstance:這種啟動(dòng)模式和"singleTask"有點(diǎn)相似,只不過(guò)系統(tǒng)不會(huì)向聲明成"singleInstance"的Activity所在的任務(wù)當(dāng)中再添加其它Activity纳像。也就是說(shuō)荆烈,這種Activity所在的任務(wù)中始終只會(huì)有一個(gè)Activity,通過(guò)這個(gè)Activity再打開(kāi)的其它Activity也會(huì)被放入到別的任務(wù)當(dāng)中竟趾。
再舉一個(gè)例子憔购,Android系統(tǒng)內(nèi)置的瀏覽器程序聲明自己瀏覽網(wǎng)頁(yè)的Activity始終應(yīng)該在一個(gè)獨(dú)立的任務(wù)當(dāng)中打開(kāi),也就是通過(guò)在<activity>元素中設(shè)置"singleTask"啟動(dòng)模式來(lái)實(shí)現(xiàn)的岔帽。這意味著玫鸟,當(dāng)你的程序準(zhǔn)備去打開(kāi)Android內(nèi)置瀏覽器的時(shí)候,新打開(kāi)的Activity并不會(huì)放入到你當(dāng)前的任務(wù)中犀勒,而是會(huì)啟動(dòng)一個(gè)新的任務(wù)屎飘。而如果瀏覽器程序在后臺(tái)已經(jīng)存在一個(gè)任務(wù)了妥曲,則會(huì)把這個(gè)任務(wù)切換到前臺(tái)。
其實(shí)不管是Activity在一個(gè)新任務(wù)當(dāng)中啟動(dòng)钦购,還是在當(dāng)前任務(wù)中啟動(dòng)逾一,返回鍵永遠(yuǎn)都會(huì)把我們帶回到之前的一個(gè)Activity中的。但是有一種情況是比較特殊的肮雨,就是如果Activity指定了啟動(dòng)模式是"singleTask",并且啟動(dòng)的是另外一個(gè)應(yīng)用程序中的Activity箱玷,這個(gè)時(shí)候當(dāng)發(fā)現(xiàn)該Activity正好處于一個(gè)后臺(tái)任務(wù)當(dāng)中的話怨规,就會(huì)直接將這整個(gè)后臺(tái)任務(wù)一起切換到前臺(tái)
啟動(dòng)方式
顯式
需要知道SecondActivity的存在
Intent intent=new Intent(MainActivity.this, SecondActivity.class);
//intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
startActivity(intent);
使用Intent flags
除了使用manifest文件之外,你也可以在調(diào)用startActivity()方法的時(shí)候锡足,為Intent加入一個(gè)flag來(lái)改變Activity與任務(wù)的關(guān)聯(lián)方式
FLAG_ACTIVITY_NEW_TASK
設(shè)置了這個(gè)flag波丰,新啟動(dòng)Activity就會(huì)被放置到一個(gè)新的任務(wù)當(dāng)中(與"singleTask"有點(diǎn)類似,但不完全一樣)舶得,當(dāng)然這里討論的仍然還是啟動(dòng)其它程序中的Activity掰烟。這個(gè)flag的作用通常是模擬一種Launcher的行為,即列出一推可以啟動(dòng)的東西沐批,但啟動(dòng)的每一個(gè)Activity都是在運(yùn)行在自己獨(dú)立的任務(wù)當(dāng)中的纫骑。FLAG_ACTIVITY_SINGLE_TOP
設(shè)置了這個(gè)flag,如果要啟動(dòng)的Activity在當(dāng)前任務(wù)中已經(jīng)存在了九孩,并且還處于棧頂?shù)奈恢孟裙荩敲淳筒粫?huì)再次創(chuàng)建這個(gè)Activity的實(shí)例,而是直接調(diào)用它的onNewIntent()方法躺彬。這種flag和在launchMode中指定"singleTop"模式所實(shí)現(xiàn)的效果是一樣的煤墙。FLAG_ACTIVITY_CLEAR_TOP
設(shè)置了這個(gè)flag,如果要啟動(dòng)的Activity在當(dāng)前任務(wù)中已經(jīng)存在了宪拥,就不會(huì)再次創(chuàng)建這個(gè)Activity的實(shí)例仿野,而是會(huì)把這個(gè)Activity之上的所有Activity全部關(guān)閉掉。比如說(shuō)她君,一個(gè)任務(wù)當(dāng)中有A脚作、B、C缔刹、D四個(gè)Activity鳖枕,然后D調(diào)用了startActivity()方法來(lái)啟動(dòng)B,并將flag指定成FLAG_ACTIVITY_CLEAR_TOP桨螺,那么此時(shí)C和D就會(huì)被關(guān)閉掉宾符,現(xiàn)在返回棧中就只剩下A和B了。
那么此時(shí)Activity B會(huì)接收到這個(gè)啟動(dòng)它的Intent灭翔,你可以決定是讓Activity B調(diào)用onNewIntent()方法(不會(huì)創(chuàng)建新的實(shí)例)魏烫,還是將Activity B銷毀掉并重新創(chuàng)建實(shí)例辣苏。如果Activity B沒(méi)有在manifest中指定任何啟動(dòng)模式(也就是"standard"模式),并且Intent中也沒(méi)有加入一個(gè)FLAG_ACTIVITY_SINGLE_TOP flag哄褒,那么此時(shí)Activity B就會(huì)銷毀掉稀蟋,然后重新創(chuàng)建實(shí)例。而如果Activity B在manifest中指定了任何一種啟動(dòng)模式呐赡,或者是在Intent中加入了一個(gè)FLAG_ACTIVITY_SINGLE_TOP flag退客,那么就會(huì)調(diào)用Activity B的onNewIntent()方法。
FLAG_ACTIVITY_CLEAR_TOP和FLAG_ACTIVITY_NEW_TASK結(jié)合在一起使用也會(huì)有比較好的效果链嘀,比如可以將一個(gè)后臺(tái)運(yùn)行的任務(wù)切換到前臺(tái)萌狂,并把目標(biāo)Activity之上的其它Activity全部關(guān)閉掉。這個(gè)功能在某些情況下非常有用怀泊,比如說(shuō)從通知欄啟動(dòng)Activity的時(shí)候茫藏。FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS Activity不會(huì)出現(xiàn)在歷史activity的列表中,等價(jià)于 xml 中配置
android:excludeFromRecents="treu"
隱式
隱式啟動(dòng)不同之處在于我們并不需要像Intent(MainActivity.this, SecondActivity.class)這樣傳參數(shù)然后再Start另一個(gè)Activity.我們需要在intent添加過(guò)濾器intentfilter霹琼。
<activity
android:name="com.example.android.tst.SecondActivity"
android:label="@string/title_activity_main" >
<intent-filter>
<action android:name="com.example.android.tst.SecondActivity"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
Intent intent=new Intent("com.example.android.tst.SecondActivity");
startActivity(intent);
- action 匹配务傲,字符串匹配(系統(tǒng)內(nèi)置,自定義)枣申,區(qū)分大小寫(xiě)售葡。一個(gè)過(guò)濾規(guī)則中可以有多個(gè)action,只要任何一個(gè)匹配成功即可
- category 匹配忠藤,也是一個(gè)字符串天通,(系統(tǒng)內(nèi)置,自定義),每一個(gè)都需要匹配成功熄驼,系統(tǒng)會(huì)自動(dòng)加上
<category android:name="android.intent.category.DEFAULT" /> 的匹配 - data 匹配像寒, scheme, host, port, path, pathPrefix, pathPattern 是用來(lái)匹配 Intent 中的 Data Uri 的。具體規(guī)則如下: scheme://host:port/path or pathPrefix or pathPattern
setType 調(diào)用后設(shè)置 mimeType瓜贾,然后將 data 置為 null诺祸;
setData 調(diào)用后設(shè)置 data,然后將 mimeType 置為 null祭芦;
setDataAndType 調(diào)用后才會(huì)同時(shí)設(shè)置 data 與 mimeType筷笨。
-
示例,短信中包含一個(gè)連接龟劲,可以直接打開(kāi)應(yīng)用
<intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:host="www.aaa.com" android:pathPrefix="/bbb" android:scheme="http" /> <data android:host="www.aaa.com" android:pathPrefix="/ccc" android:scheme="http" /> </intent-filter>
清空返回棧
如果用戶將任務(wù)切換到后臺(tái)之后過(guò)了很長(zhǎng)一段時(shí)間胃夏,系統(tǒng)會(huì)將這個(gè)任務(wù)中除了最底層的那個(gè)Activity之外的其它所有Activity全部清除掉。當(dāng)用戶重新回到這個(gè)任務(wù)的時(shí)候昌跌,最底層的那個(gè)Activity將得到恢復(fù)仰禀。這個(gè)是系統(tǒng)默認(rèn)的行為,因?yàn)榧热贿^(guò)了這么長(zhǎng)的一段時(shí)間蚕愤,用戶很有可能早就忘記了當(dāng)時(shí)正在做什么答恶,那么重新回到這個(gè)任務(wù)的時(shí)候饺蚊,基本上應(yīng)該是要去做點(diǎn)新的事情了。
當(dāng)然悬嗓,既然說(shuō)是默認(rèn)的行為污呼,那就說(shuō)明我們肯定是有辦法來(lái)改變的,在<activity>元素中設(shè)置以下幾種屬性就可以改變系統(tǒng)這一默認(rèn)行為:
- alwaysRetainTaskState
如果將最底層的那個(gè)Activity的這個(gè)屬性設(shè)置為true包竹,那么上面所描述的默認(rèn)行為就將不會(huì)發(fā)生燕酷,任務(wù)中所有的Activity即使過(guò)了很長(zhǎng)一段時(shí)間之后仍然會(huì)被繼續(xù)保留。 - clearTaskOnLaunch
如果將最底層的那個(gè)Activity的這個(gè)屬性設(shè)置為true周瞎,那么只要用戶離開(kāi)了當(dāng)前任務(wù)苗缩,再次返回的時(shí)候就會(huì)將最底層Activity之上的所有其它Activity全部清除掉。簡(jiǎn)單來(lái)講堰氓,就是一種和alwaysRetainTaskState完全相反的工作模式,它保證每次返回任務(wù)的時(shí)候都會(huì)是一種初始化狀態(tài)苹享,即使用戶僅僅離開(kāi)了很短的一段時(shí)間双絮。 - finishOnTaskLaunch
這個(gè)屬性和clearTaskOnLaunch是比較類似的,不過(guò)它不是作用于整個(gè)任務(wù)上的得问,而是作用于單個(gè)Activity上囤攀。如果某個(gè)Activity將這個(gè)屬性設(shè)置成true,那么用戶一旦離開(kāi)了當(dāng)前任務(wù)宫纬,再次返回時(shí)這個(gè)Activity就會(huì)被清除掉焚挠。