最近想寫篇關于Activity啟動過程源碼分析的博客,在此之前先總結下Android中Activity必須要知道的一些基礎知識,以方便后面能看懂Activity的源碼。
### 一,Activity生命周期和啟動模式
activity最經典的啟動模式圖如下:

它分為onCreate--onStart--onResume--onPause--onStop--onDestory.這幾個階段,這個是個android開發者肯定都很熟悉,這里不詳細說,只是說下一些注意事項:
1.onStart和onStop的區別:onStart表示應用己經可見,但只運行在后臺,沒到前臺。onStop表示acitvity運行在后臺。當用戶使用透明主題,不會調用onstop.
2.onResume和onpause的區別:這兩個是從activity是否位于前臺來回調的,是一組。
3.當新Activity啟動之前,棧頂acitivity需要先onPause新的再啟動。所以不能在onpause中做耗時操作。?
4.當activity異常停止時,會調用onSaveInstanceState,并把所保存的Bundle傳遞給onRestoreInstanceState,onRestoreInstanceState是在onStart之后被調用。過程是onSaveInstanceState先保存數據,Activity會委托Window保存數據,接著Window再委托上面的頂級容器去保存,一直往上委托直到DecorView,最后它再一一通知它的子元素來保存數據。典型的委托思想。 ??
如果onRestoreInstanceState被調用 ,那它的onSaveInstanceState參數一定有值。
5.在資源不足情況下導致的activity被殺死也會調用onSaveInstanceState。activity有三個優先級:
* 前臺activity。
* 可見但非前臺activity(如Dialog)
* 后臺activity(onstop的情況)。
### 二,啟動模式
1.啟動模式介紹:
android有四種模式,分別是standard,singleTop,singleTask,singleInstance。
standard:一個任務棧可以有多個實例,每個實例可以屬于不同任務棧。每新建一個activity就新建一個實例。一個實例被哪個實例創建,就存在哪個實例所在的棧中,如A啟動了B,那么B就位于A的棧中。不能在appliactionContext中啟動它,因為非activity的context沒有任務棧,解決方法是加上FLAG_ACTIVITY_NEW_TASK標識,會新建一個任務棧。
singleTop:如果activity存在棧頂,此時activity不會被重建,它的oncreate等方法不會被重調用 。如棧中有ABC,再啟動C,就不會重新創建C。
singleTask:棧內復用模式,首先判斷所需要的棧是否在否存在,若存在,那么只要在棧中存在,就不新建實例,并cleanTop,如果不存在,新建實例。如果所要的棧都不存在,新建棧。如棧中有ABCD,啟動C,C指定了所需的棧且棧不存在,那么就會創建一個新棧,并把C存入,此時就存在兩個棧,一個是ABC,一個是C。如棧中有ABCD,啟動的C所需的棧就是ABCD所在的棧,那就會把C置于棧項,C上的所有實例出棧,此時棧就變成了ABC。那么如何指定所需任務棧。一般使用TaskAffinity來指定,下面會說明。
singleInstance:具有singleTask的所有特性。不同的是,具有此模式的acitivity只能單獨位于一個棧中。如創建了A,A在一個棧中,后續再創建A就不會再創建實例了。
指定啟動模式有兩種設置方法:
在xml中設置:andorid:launchMode="singleTop"
在代碼中設置:intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);這種方法的優點是優先級比第一種高,比如同時用兩種方法設置,那以第二種為主,缺點是它不能設置singleInstance。
2.所需任務棧:
TaskAffinity:標識了一個activity所需要的任務棧名稱。默認為應用的包名。主要和singleTask配對使用。
任務棧分為前臺和后臺任務棧。后臺 任務棧是指位于暫停的狀態。用戶可以切換將后臺再次調到前臺。
A啟動B,則B會位于A的任務棧中。(沒有TaskAffinity情況下)?
比如A啟動B,B的TaskAffinity與A的不同,那就會創建新任務棧并把B放入。
AB是前臺棧,CD是后臺棧,B啟動D,則變成ABCD,啟動C則變成ABC.
3.標志位:
我們經常會在代碼中指定標志位,主要的標志位有以下幾種:
FLAG_ACTIVITY_NEW_TASK:類似singleTask
FLAG_ACTIVITY_SINGLE_TOP:類似singleTop
FLAG_ACTIVITY_CLEAN_TOP:清當前activity棧中它本身以上的activity
FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS:具有這個標記的activity不會出現在歷史activity列表中。只需設置
android:excludeFromRecents="true"
### 三,IntentFilter匹配規則
啟動activity有顯式和隱式兩種,如果是隱式,就要滿足IntentFilter匹配規則。
intent 有action,category,data.三個屬性。只有一個intent同時匹配了action,category和data才算完全匹配。有多個filter只要有一個匹配就可以。
action只要有一個匹配就可以。
category:如果intent有這個屬性,那它所有的category都必須匹配上。可以沒有。沒有默認有DEFAULT這個屬性。為了我們的activity能接受隱式調用,就必須加上android.intent.category.DEFAULT這個屬性。
data:與action類似。它為分為兩部分。mimeType,URL.mineType指媒體類型,如image/jpeg等,URL如下
[http://www.baidu.com:80/search/info](http://www.baidu.com/search/info)
URL默認是content和file,在不指定data 情況下就是匹配它。調用的方法如下
intent.setDataAndType(Uri.parse("file://abc"),"image/png")
完整的代碼如下:?
~~~
Intent intent = new Intent("com.lxj.a");
intent.addCategory("com.lxj.b");
intent.setDataAndType(Uri.parse("file://abc"),"image/png")
startActivity(intent);
匹配的是如下的activity
<activity …………>
<intent-filter>
<action android:name="com.lxj.a"/>
<actegory android:name="com.lxj.b"/>
<actegory android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="text/plain"/>
<data android:mimeType="image/*"/>
</intent-filter>
<activity/>
~~~
就先寫這么多吧,下一篇我會介紹下我對activity啟動源碼的理解。
- 前言
- Android底部tab與標題欄相結合
- Android免費獲取短信驗證碼
- android中Handler的源碼分析
- 詳解Fragment的傳值問題
- 詳談gson解析
- android新控件之toolbar,floatingActionButton,SnackBar,CollapsingToolbarLayout
- android自定義控件
- 淺談android的線程池
- Android的消息處理機制,AsyncTask源碼解析
- IPC——android進程間通信
- CoCos2d_android入門所需知道的一切
- Cocos2d_android你所需要知道的一切(下)
- Activity你需要知道的一切
- Activity啟動過程源碼分析
- Data Binding Guide——google官方文檔翻譯(上)
- Data Binding Guide——google官方文檔翻譯(下)
- android TextView實現跑馬燈效果
- android中生成excel
- Volley源碼解析
- LayoutInflater源碼解析
- android發送郵件
- android測試工具MonkeyRunner--google官網翻譯
- android View繪制源碼分析
- Android中Window添加View的底層原理
- 仿美團商品選購下拉菜單實現