前言
本文已經收錄到我的Github個人博客,歡迎大佬們光臨寒舍:
本篇文章需要已經具備的知識:
- Activity的基本概念
-
AndroidManifest.xml
的基本概念
學習清單:
- Activity的生命周期
- Fragment的生命周期
- Activity的啟動模式
- IntentFilter的匹配規(guī)則
一.為什么要深入了解Activity
呢?
Activity
翻譯為活動烹玉,在Android
中代表了界面和以界面為中心相應的業(yè)務邏輯伯病,包括顯示、與用戶交互等,它也是四大組件之一点骑,重要性不言而喻泛范。并且让虐,許多公司在考察Android
的知識點的時候,經常會考察到Activity
的知識罢荡。
因此赡突,深入了解Activity,不僅對你日常的開發(fā)有幫助区赵,還對你之后找工作有所增益惭缰。
二.核心知識點歸納
2.1 生命周期全解析
2.1.1 典型情況下的生命周期
2.1.1.1 Activity生命周期圖解
2.1.1.2 Activity切換過程
(1)啟動Activity
(2)打開新的Activity / 切換到桌面
- 正常情況:
onPause()
-->onStop()
- 特殊情況:當新的
Activity
使用了透明主題,當前的Activity
不會回調onStop笼才,會停留在Paused
想要了解Android 透明主題的可以點擊鏈接:Android透明主題
(3)返回舊的Activity
-
當舊的Activity不可見:
當舊的Activity不可見 當舊的Activity可見:
問題思考:當前Activity為A漱受,打開新的ActivityB,那么B的
onResume()
和A的onPause()
的執(zhí)行順序是怎樣的呢?
答案:AonPause()
-->BonResume()
,要得到這個答案骡送,需要對Activity的工作原理有所了解昂羡,筆者在本系列文章的后面幾篇會介紹。
小Tips:要關閉Activity的時候摔踱,盡量在
onStop()
中進行耗時操作虐先,而使得新Activity盡快顯示出來。
2.1.2 異常情況下的生命周期
2.1.2.1 異常情況下數(shù)據(jù)的保存和恢復
這個涉及到onSaveInstanceState
和onRestoreInstanceState
方法昌渤,具體可見下圖
需要特別留意的是:
onSaveInstanceState
的執(zhí)行順序赴穗,是在onStop
之前,與onPause
沒有既定順序onRestoreInstanceState
的執(zhí)行順序,是在onStart
之后
Q1:其中保存和恢復View的工作流程是怎樣的呢膀息?
可以看出般眉,保存和恢復View的工作流程是典型的委托思想,上層委托下層潜支,父容器委托子元素處理事情甸赃。
后面會講到的
View
的繪制流程,事件分發(fā)機制等冗酿,都是才有類似的思想埠对。
Q2:其中數(shù)據(jù)恢復的方式有哪些络断?
-
在onCreate中恢復
需要注意的是,必須要判斷Bundle是否為空
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//方法一:在onCreate中調用緩存恢復數(shù)據(jù)项玛,必須要判斷savedInstanceState是否為空
if (savedInstanceState != null) {
String test = savedInstanceState.getString("extra_test");
Log.d(TAG, "[onCreate]restore extra_test:" + test);
}
}
-
在onRestoreInstanceState中恢復
Bundle一定有值貌笨,不需要判斷是否為空,是官方推薦的恢復數(shù)據(jù)的方法
//利用onRestoreInstanceState
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
String test = savedInstanceState.getString("extra_test");
Log.d(TAG, "[onRestoreInstanceState]restore extra_test:" + test);
}
2.1.2.2 系統(tǒng)配置變化導致的異常
Q1:發(fā)生改變的系統(tǒng)配置通常有哪些襟沮?
- locale:一般指切換了系統(tǒng)語言
- orientation:旋轉屏幕
- keyboardHidden:鍵盤的可訪問性發(fā)生變化锥惋,比如:調出鍵盤
Q2:想系統(tǒng)配置改變后,activity不被重新創(chuàng)建开伏,應該怎么辦膀跌?
在
ActivityManifest.xml
中,對應的Activity
的configChanges
屬性中指定該選項
<activity
android:name="com.ryg.chapter_1.MainActivity"
android:configChanges="orientation|screenSize"
android:label="@string/app_name"
android:launchMode="standard" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
2.1.2.3 資源內存不足導致的異常
這種情況應該很容易理解固灵,類比于:當使用小內存手機的時候捅伤,會發(fā)現(xiàn)某些應用經常一切換后臺,就會自動關閉了巫玻,原理也是資源內存不足丛忆,被系統(tǒng)自動回收了。
Q1:Activity
的優(yōu)先級排序是什么大审?
由上到下蘸际,優(yōu)先級由高到低
- 前臺
Activity
--正在和用戶交互 - 可見非前臺
Activity
--比如說,彈出新的對話框徒扶,對話框后面的Activity
即屬于可見非前臺Activity
- 后臺
Activity
--已經被停止的Activity
Q2:怎么提高后臺工作的優(yōu)先級呢?
將后臺工作放入Service
中根穷,保證進程有一定的優(yōu)先級
2.1.3 Fragment
的生命周期
因為本篇是
Activity
篇姜骡,筆者不便大費周章地敘述,為了滿足求知欲強的讀者屿良,筆者特地推薦一篇:Fragment生命周期圈澈,里面寫得非常詳細
2.2 Activity
啟動模式
2.2.1 Activity
的四種啟動模式
a:standard
:標準模式
- 含義:每次啟動一個Activity就會創(chuàng)建一個新的實例,而不管實例存在與否尘惧。
- 注意:使用
ApplicationContext
去啟動standard
模式Activity
就會報錯康栈。因為standard模式的Activity會默認進入啟動它所屬的任務棧,但是由于非Activity的Context沒有所謂的任務棧喷橙,所以就會報錯啥么。
b:singleTop
:棧頂復用模式
- 含義:如果新Activity已經位于任務棧的棧頂,就不會重新創(chuàng)建贰逾,并回調onNewIntent(intent)方法悬荣。
c:singleTask
:棧內復用模式
- 含義:只要Activity在一個棧中存在,都不會重新創(chuàng)建疙剑,并回調
onNewIntent(intent)
方法氯迂。如果不存在践叠,系統(tǒng)會先尋找是否存在需要的棧,如果不存在該棧嚼蚀,就創(chuàng)建一個任務棧禁灼,并把該Activity放進去;如果存在轿曙,就會查看棧中是否有實例存在弄捕,若實例存在,則將實例調到棧頂拳芙,并回調onNewIntent(intent)
方法察藐,否則創(chuàng)建實例到已經存在的棧中。
d:singleInstance
:單實例模式
- 含義: 具有此模式的Activity只能單獨位于一個任務棧中舟扎,且此任務棧中只有唯一一個實例分飞。
標識Activity任務棧名稱的屬性:
android:taskAffinity
,默認為應用包名睹限。
2.2.2 Activity
的Flags
Flags有很多譬猫,這里介紹幾個常用的Flags
-
FLAG_ACTIVITY_NEW_TASK
:指定singleTask
模式 -
FLAG_ACTIVITY_SINGLE_TOP
:指定singleTop
模式 -
FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
:指定新的Activity不會出現(xiàn)在最近啟動的Activity的列表中
2.3 IntentFilter的匹配規(guī)則
原則:
- 一個intent只有同時匹配某個Activity的intent-filter中的
action
、category
羡疗、data
才算完全匹配染服,才能啟動該Activity。- 一個Activity可以有多個intent-filter叨恨,一個 intent只要成功匹配任意一組 intent-filter柳刮,就可以啟動該Activity。
Q1:action
的匹配規(guī)則
- 只要Intent中的存在一個action且能夠和任何一個 intent-filter中的action相同即可成功匹配
- 區(qū)分大小寫
- 必須存在
Q2:category
的匹配規(guī)則
- 有其他
category
痒钝,則要求intent中的category
和intent-filter中的所有category
相同秉颗。 - 非必須,這是因為此時系統(tǒng)給該Activity 默認加上了
< category android:name="android.intent.category.DEAFAULT" />
屬性值送矩。
Q3:data
匹配規(guī)則
- 類似于
action
- URI非必須指定蚕甥,默認值為
content
和file
需要注意的是,為
Intent
指定完整的data的時候栋荸,要調用setDataAndType(URI,mimeType)
方法
intent.setDataAndType(Uri.parse("file://abc"),"video/png");
采用隱式方式啟動Activity時菇怀,可以用
PackageManager
的resolveActivity(Intent)
方法或者Intent
的resolveActivity(Intent)
方法,來判斷是否有Activity匹配該隱式Intent,如果匹配不到晌块,會返回NULL
三.課堂小測試
恭喜你爱沟,已經看完了前面的文章,相信你對
Activity
已經有一定深度的了解摸袁,下面钥顽,進行一下課堂小測試,驗證一下自己的學習成果吧靠汁!
題目情景:有三個
Activity
蜂大,分別名為A
,B
,C
闽铐,A
的啟動模式是standard
,B
和C
的啟動模式是singleTask
,現(xiàn)在進行如下操作:A啟動了B奶浦,B啟動了C兄墅,C啟動了A,A再啟動B澳叉,現(xiàn)在連按2次BACK
隙咸,你看到的是哪個Activity
?-
答案揭曉:回到桌面成洗,具體過程可以參考下面的流程圖
流程圖
如果文章對您有一點幫助的話五督,希望您能點一下贊,您的點贊瓶殃,是我前進的動力
本文參考鏈接:
- Android透明主題
- Fragment生命周期
- 《Android開發(fā)藝術探索》
- Activity到底是什么(新手學Android)
- Android Activity生命周期大全詳解
- 要點提煉|開發(fā)藝術之Activity