Android?任務(wù)棧機(jī)制詳解
1.XML配置的幾種方式詳解
首先,我們知道,android有任務(wù)棧機(jī)制,啟動(dòng)任務(wù)棧的方式有xml中配置,還有就是通過intent設(shè)置flag去啟動(dòng)相應(yīng)的activity。這里我們分三部分來介紹 1.xml配置的幾種方式詳解 2.intent flag啟動(dòng)的幾種方式詳解 3.flag 與 xml 幾種方式的區(qū)別和聯(lián)系
Android開發(fā)者在AndroidMainifest文件中一共設(shè)計(jì)了四種啟動(dòng)模式,如下所示
1.1 standard
默認(rèn)的啟動(dòng)模式,如果不指定Activity的啟動(dòng)模式,則使用這種方式啟動(dòng)Activity。這種啟動(dòng)模式每次都會(huì)創(chuàng)建新的實(shí)例,每次點(diǎn)擊standard模式創(chuàng)建Activity后,都會(huì)創(chuàng)建新的MainActivity覆蓋在原Activity上。 實(shí)際代碼驗(yàn)證 我們實(shí)例代碼驗(yàn)證一下,新建三個(gè)activity,xml中不配置任務(wù)棧方式(默認(rèn)為標(biāo)準(zhǔn)棧),三個(gè)activity相互跳轉(zhuǎn),代碼如下:
package com.itbird.task; import android.content.Intent; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import androidx.appcompat.app.AppCompatActivity; import com.itbird.R; import com.itbird.bitmapOOM.BitmapUtils; import com.itbird.viewEvent.MyView; public class MainTestActivity extends AppCompatActivity { private static final String TAG = MainTestActivity.class.getSimpleName(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.task_test); Button button = findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(MainTestActivity.this, SecondTestActivity.class); startActivity(intent); } }); } @Override protected void onNewIntent(Intent intent) { Log.e(TAG, TAG + " onNewIntent"); super.onNewIntent(intent); } @Override protected void onDestroy() { Log.e(TAG, TAG + " onDestroy"); super.onDestroy(); } }
運(yùn)行之后,跳轉(zhuǎn)順序?yàn)?-2-3-1,通過adb命令查看后臺(tái)任務(wù)棧信息adb shell dumpsys activity activities | grep com.itbird
我們看到后臺(tái)任務(wù)棧,的確是保持為同一個(gè),而且activity實(shí)例一直是新建累加的。
1.2 singleTop
如果指定啟動(dòng)Activity為singleTop模式,那么在啟動(dòng)時(shí),系統(tǒng)會(huì)判斷當(dāng)前棧頂Activity是不是要啟動(dòng)的Activity,如果是則不創(chuàng)建新的的Activity而直接引用這個(gè)Activity;如果不是則創(chuàng)建新的Activity。 實(shí)際代碼驗(yàn)證 我們?cè)诘谝粋€(gè)樣例的基礎(chǔ)代碼上,把第三個(gè)activity任務(wù)棧模式改為singleTop,相同的跳轉(zhuǎn)邏輯,1-2-3-3,運(yùn)行查看一下任務(wù)棧信息
1.3 singleTask
singliTask模式與singleTop模式類似,只不過singleTop是堅(jiān)持棧頂元素是否是需要啟動(dòng)的Activity,而singleTask是檢測(cè)整個(gè)Activity棧中是否存在需要啟動(dòng)的Activity。如果存在,則將該Activity置于棧頂,并將該Activity以上的Activity都銷毀。不過這里是指在同一個(gè)App中啟動(dòng)這個(gè)singleTask的Activity,如果是其他程序以singleTask模式來啟動(dòng)這個(gè)Activity,那么它將創(chuàng)建一個(gè)新的任務(wù)棧。不過這里有一點(diǎn)需要注意的是,如果啟動(dòng)的模式為singleTask的Activity已經(jīng)在后臺(tái)一個(gè)任務(wù)棧中了,那么啟動(dòng)后,后臺(tái)的這個(gè)任務(wù)棧將一起被切換到前臺(tái)。 實(shí)際代碼驗(yàn)證 我們?cè)诘谝粋€(gè)樣例的基礎(chǔ)代碼上,把第一個(gè)activity任務(wù)棧模式改為singleTask,相同的跳轉(zhuǎn)邏輯,1-2-3-1,運(yùn)行查看一下任務(wù)棧信息
1.4 singleInstance
singleInstance這種模式和使用閱覽器工資類似。在多個(gè)系統(tǒng)訪問閱覽器時(shí),如果當(dāng)前閱覽器沒有打開,則打開閱覽器,否則會(huì)在當(dāng)前打開的閱覽器中訪問。申明為singleInstance的Activity會(huì)出現(xiàn)在一個(gè)新的任務(wù)棧中,而且這個(gè)任務(wù)棧只會(huì)存在一個(gè)Activity。 實(shí)際代碼驗(yàn)證 我們?cè)诘谝粋€(gè)樣例的基礎(chǔ)代碼上,把第三個(gè)activity任務(wù)棧模式改為singleInstance,相同的跳轉(zhuǎn)邏輯,1-2-3-3,運(yùn)行查看一下任務(wù)棧信息
2.Intent flag啟動(dòng)的幾種方式詳解
2.1 單獨(dú)使用
- FLAG_ACTIVITY_NEW_TASK 加上 FLAG_ACTIVITY_NEW_TASK flag 后,啟動(dòng)一個(gè) Activity 時(shí),如果需要?jiǎng)?chuàng)建,被啟動(dòng)的 Activity 會(huì)在它需要的棧中創(chuàng)建。如 A 啟動(dòng) B,B 會(huì)在 B 自己需要的棧中被創(chuàng)建(即 taskAffinity 指定的棧)。
我們還是以之前的三個(gè)界面的例子,三個(gè)界面的xml配置啟動(dòng)棧方式都為標(biāo)準(zhǔn)棧,跳轉(zhuǎn)順序?yàn)?-2-3-1,跳轉(zhuǎn)過程中使用FLAG_ACTIVITY_NEW_TASK flag,代碼:
Intent intent = new Intent(MainTestActivity.this, SecondTestActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent);
可以看到,在一個(gè)任務(wù)棧中,即使重新啟動(dòng)1,也是新建實(shí)例1,也就是說,這個(gè)Flag只是去找尋親和屬性的?;蛘咝陆?,并不對(duì)棧內(nèi)的實(shí)例進(jìn)行復(fù)用、清空等操作。這里看出來了吧,F(xiàn)LAG_ACTIVITY_NEW_TASK != singleTask哦,網(wǎng)上有很多誤人子弟的文章,大家還是自己實(shí)踐出真知吧
- FLAG_ACTIVITY_CLEAR_TOP 我們還是以之前的三個(gè)界面的例子,三個(gè)界面的xml配置啟動(dòng)棧方式都為標(biāo)準(zhǔn)棧,跳轉(zhuǎn)順序?yàn)?-2-3-1,跳轉(zhuǎn)過程中使用FLAG_ACTIVITY_CLEAR_TOP flag,代碼:
Intent intent = new Intent(MainTestActivity.this, SecondTestActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); startActivity(intent);
這時(shí)肯定有小伙伴問了,這不就和singleTask一樣的效果了嗎?我很確定的告訴您,不是哦~~~,clear_top如果檢測(cè)到棧中有實(shí)例存在,會(huì)清空棧內(nèi)包含本身的以上所有activity,我們看一下activity 1的log日志打印就知道了
所以,這里我們知道一個(gè)關(guān)鍵點(diǎn):這里看出來了吧,F(xiàn)LAG_ACTIVITY_CLEAR_TOP != singleTask哦,網(wǎng)上有很多誤人子弟的文章,大家還是自己實(shí)踐出真知吧
- FLAG_ACTIVITY_SINGLE_TOP 我們還是以之前的三個(gè)界面的例子,三個(gè)界面的xml配置啟動(dòng)棧方式都為標(biāo)準(zhǔn)棧,跳轉(zhuǎn)順序?yàn)?-2-3-3,跳轉(zhuǎn)過程中使用FLAG_ACTIVITY_SINGLE_TOP flag,代碼:
Intent intent = new Intent(MainTestActivity.this, SecondTestActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); startActivity(intent);
從這里可以看出,F(xiàn)LAG_ACTIVITY_SINGLE_TOP == singleTop哦
2.2 組合使用
針對(duì)于組合使用,我們直接說結(jié)論吧,依然是上面的例子,很好驗(yàn)證
- FLAG_ACTIVITY_NEW_TASK + FLAG_ACTIVITY_SINGLE_TOP activity 在前臺(tái)(當(dāng)前顯示的棧的棧頂),不創(chuàng)建,它自己 onNewIntent 被調(diào)用;activity 不在前臺(tái)的情形下,activity 需要的棧存在,在該棧中創(chuàng)建一個(gè) activity 或?qū)⒃摋R浦燎芭_(tái)(它自己 onNewIntent 被調(diào)用),activity 需要的棧不存在,創(chuàng)建一個(gè)它需要的棧,再創(chuàng)建 activity
- FLAG_ACTIVITY_NEW_TASK + FLAG_ACTIVITY_CLEAR_TOP activity 在它需要的棧里存在,它上面的 activity 會(huì)出棧,它自己 finish 后重建 activity 在它需要的棧里不存在,在它需要的棧里創(chuàng)建 所以此處備注:
FLAG_ACTIVITY_NEW_TASK + FLAG_ACTIVITY_CLEAR_TOP != singleTask
- FLAG_ACTIVITY_CLEAR_TOP + FLAG_ACTIVITY_SINGLE_TOP activity 在前臺(tái)(當(dāng)前顯示的棧的棧頂),不創(chuàng)建,它自己 onNewIntent 被調(diào)用;activity 不在前臺(tái)的情形下,activity 在它需要的棧里存在,它上面的 activity 會(huì)出棧,它自己 onNewIntent 被調(diào)用,activity 在它需要的棧里不存在,在它需要的棧里創(chuàng)建。 所以此處備注:
FLAG_ACTIVITY_SINGLE_TOP + FLAG_ACTIVITY_CLEAR_TOP == singleTask
3.flag 與 xml 幾種方式的區(qū)別和聯(lián)系
其實(shí)相關(guān)區(qū)別和聯(lián)系在上面已經(jīng)基本都說過了,這里用等式簡(jiǎn)單總結(jié)一下: FLAG_ACTIVITY_NEW_TASK != singleTask
FLAG_ACTIVITY_CLEAR_TOP != singleTask
FLAG_ACTIVITY_NEW_TASK + FLAG_ACTIVITY_CLEAR_TOP != singleTask
FLAG_ACTIVITY_SINGLE_TOP + FLAG_ACTIVITY_CLEAR_TOP == singleTask
FLAG_ACTIVITY_SINGLE_TOP == singleTop
當(dāng)然這些結(jié)論都是基于最初的activity是標(biāo)準(zhǔn)棧的前提,如果將activity最初xml配置改為其他啟動(dòng)棧模式,結(jié)論可能有些就發(fā)生了一點(diǎn)點(diǎn)的改變。 我們不需要死記硬背這些知識(shí),這些知識(shí)點(diǎn)最好各位結(jié)合自己的實(shí)踐Demo驗(yàn)證一波,同時(shí)記住一點(diǎn),F(xiàn)LAG_ACTIVITY_NEW_TASK 只是針對(duì)于棧的描述,F(xiàn)LAG_ACTIVITY_CLEAR_TOP 會(huì)銷毀本身,這就行了。
以上就是Android 任務(wù)棧機(jī)制詳解的詳細(xì)內(nèi)容,更多關(guān)于Android 任務(wù)棧機(jī)制的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Android仿抖音右滑清屏左滑列表功能的實(shí)現(xiàn)代碼
這篇文章主要介紹了Android仿抖音右滑清屏左滑列表功能,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-06-06Android利用ZXing掃描二維碼的實(shí)例代碼解析
這篇文章主要介紹了Android利用ZXing掃描二維碼的實(shí)例解析,代碼簡(jiǎn)單易懂,非常不錯(cuò),需要的朋友可以參考下2016-12-12詳解Android系統(tǒng)中跨應(yīng)用數(shù)據(jù)分享功能的實(shí)現(xiàn)
這篇文章主要介紹了Android系統(tǒng)中跨應(yīng)用數(shù)據(jù)分享功能的實(shí)現(xiàn),文中分為發(fā)送文字、二進(jìn)制內(nèi)容和圖片三種情況來講,需要的朋友可以參考下2016-04-04基于android中讀取assets目錄下a.txt文件并進(jìn)行解析的深入分析
本篇文章是對(duì)在android需要中讀取assets目錄下a.txt文件進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05Android標(biāo)題欄上添加多個(gè)Menu按鈕的實(shí)例
這篇文章主要介紹了Android標(biāo)題欄上添加多個(gè)Menu按鈕的實(shí)例的相關(guān)資料,這里提供簡(jiǎn)單實(shí)例說明如何添加多個(gè)menu按鈕的方法,需要的朋友可以參考下2017-09-09Android進(jìn)階Hook攔截系統(tǒng)實(shí)例化View過程實(shí)現(xiàn)App換膚功能
這篇文章主要為大家介紹了Android進(jìn)階Hook攔截系統(tǒng)實(shí)例化View過程實(shí)現(xiàn)App換膚功能詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01Android系統(tǒng)自帶樣式 (android:theme)
Android系統(tǒng)中自帶樣式分享,需要的朋友可以參考下2013-01-01