真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Activity啟動(dòng)模式和taskAffinity屬性詳解

歡迎訪問我的個(gè)人博客 傳送門

10年積累的成都網(wǎng)站制作、成都網(wǎng)站建設(shè)、外貿(mào)營銷網(wǎng)站建設(shè)經(jīng)驗(yàn),可以快速應(yīng)對(duì)客戶對(duì)網(wǎng)站的新想法和需求。提供各種問題對(duì)應(yīng)的解決方案。讓選擇我們的客戶得到更好、更有力的網(wǎng)絡(luò)服務(wù)。我雖然不認(rèn)識(shí)你,你也不認(rèn)識(shí)我。但先網(wǎng)站制作后付款的網(wǎng)站建設(shè)流程,更有大安免費(fèi)網(wǎng)站建設(shè)讓你可以放心的選擇與我們合作。

任務(wù)和返回棧

應(yīng)用通常包含多個(gè) Activity ,每個(gè) Activity 均應(yīng)圍繞用戶可以執(zhí)行的特定操作設(shè)計(jì),并且能夠啟動(dòng)其他 Activity,一個(gè) Activity 可以啟動(dòng)設(shè)備上其他應(yīng)用中的 Activity,即使兩個(gè) Activity 可能來自不同的應(yīng)用,但是 Android 仍會(huì)將 Activity 保留在相同的任務(wù)中,以維護(hù)這種無縫的用戶體驗(yàn)。這里所說的任務(wù)就是指在執(zhí)行特定作業(yè)時(shí)與用戶交互的一系列 Activity,這些 Activity 按照各自的打開順序排列在堆棧(即返回棧)中。返回棧以“后進(jìn)先出”對(duì)象結(jié)構(gòu)運(yùn)行,如下圖

Activity 啟動(dòng)模式和 taskAffinity 屬性詳解

如果要查看 Activity Task棧的情況,可以在命令行用 adb 命令查看

adb shell dumpsys activity activities

執(zhí)行命令會(huì)出現(xiàn)很長一段詳細(xì)信息 找到 Running activities 即可查看,如下圖
Activity 啟動(dòng)模式和 taskAffinity 屬性詳解

啟動(dòng)模式

在了解了任務(wù)和返回棧后,我們來說說啟動(dòng)模式,上圖的堆棧是比較常規(guī)的,如果我們一直啟動(dòng)同一個(gè) Activity 系統(tǒng)會(huì)重復(fù)創(chuàng)建多個(gè)實(shí)例,但這不是我們想要的結(jié)果。這時(shí)候?yàn)榱藵M足我們的需求就需要使用 Android 提供的啟動(dòng)模式來修改系統(tǒng)的默認(rèn)行為。目前有四種啟動(dòng)模式:standard、singleTop、singleTask 和 singleInstance。在 AndroidManifest.xml 中配置即可,如下:

   
    

standard 默認(rèn)模式

系統(tǒng)在啟動(dòng) Activity 的任務(wù)中創(chuàng)建 Activity 的新實(shí)例并向其傳送 Intent。Activity 可以多次實(shí)例化,不管這個(gè)實(shí)例是否已經(jīng)存在,而每個(gè)實(shí)例均可屬于不同的任務(wù),并且一個(gè)任務(wù)可以擁有多個(gè)實(shí)例。這種模式的 Activity 被創(chuàng)建時(shí)它的 onCreate、onStart 都會(huì)被調(diào)用。這是一種典型的多實(shí)例實(shí)現(xiàn),一個(gè)任務(wù)棧中可以有多個(gè)實(shí)例,每個(gè)實(shí)例也可以屬于不同的任務(wù)棧。在這種模式下,誰啟動(dòng)了這個(gè) Activity,那么這個(gè) Activity 就運(yùn)行在啟動(dòng)它的那個(gè) Activity 所在的棧中。

這里通過簡單的代碼來驗(yàn)證,先實(shí)現(xiàn)方法來打印 Activity 的生命周期調(diào)用過程和 Taskid

fun printTaskInfo(activity: Activity, methodName: String) {
    log("${activity.localClassName} $methodName taskId = ${activity.taskId}")
}

fun log(message: String, tag: String = "debugLog") {
    Log.i(tag, message)
}

/**
 * @param T 目標(biāo) Activity
 */
inline fun  Context.toActivity() {
    startActivity(Intent(this, T::class.java))
}

界面很簡單就一個(gè)按鈕,就不截圖了,Activity 代碼

class A : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_a)
        printTaskInfo(this,"onCreate")
    }

    override fun onNewIntent(intent: Intent?) {
        super.onNewIntent(intent)
        printTaskInfo(this,"onNewIntent")
    }

    override fun onStart() {
        super.onStart()
        printTaskInfo(this,"onStart")
    }

    fun click(view: View?) {
        toActivity()
    }
}

啟動(dòng) A 然后點(diǎn)擊兩下按鈕,日志如下:

01-02 22:07:00.330 28281-28281/com.will.testdemo I/debugLog: launchmode.A onCreate taskId = 44
01-02 22:07:00.332 28281-28281/com.will.testdemo I/debugLog: launchmode.A onStart taskId = 44
01-02 22:07:01.580 28281-28281/com.will.testdemo I/debugLog: launchmode.A onCreate taskId = 44
01-02 22:07:01.582 28281-28281/com.will.testdemo I/debugLog: launchmode.A onStart taskId = 44
01-02 22:07:02.325 28281-28281/com.will.testdemo I/debugLog: launchmode.A onCreate taskId = 44
01-02 22:07:02.327 28281-28281/com.will.testdemo I/debugLog: launchmode.A onStart taskId = 44

使用 adb 命令查看 Activity Task 棧,可以看出每啟動(dòng)一次 A 都會(huì)創(chuàng)建一次實(shí)例,不管這個(gè)實(shí)例是否已經(jīng)存在
Activity 啟動(dòng)模式和 taskAffinity 屬性詳解

singleTop 棧頂復(fù)用模式

在這種模式下,如果當(dāng)前任務(wù)的頂部已存在 Activity 的一個(gè)實(shí)例,則系統(tǒng)會(huì)通過調(diào)用該實(shí)例的 onNewIntent() 方法向其傳送 Intent,而不是創(chuàng)建 Activity 的新實(shí)例。Activity 可以多次實(shí)例化,而每個(gè)實(shí)例均可屬于不同的任務(wù),并且一個(gè)任務(wù)可以擁有多個(gè)實(shí)例(但前提是位于返回棧頂部的 Activity 并不是 Activity 的現(xiàn)有實(shí)例)。這個(gè) Activity 的 onCreate、onStart 不會(huì)被系統(tǒng)調(diào)用,因?yàn)樗]有發(fā)生改變。

Activity 啟動(dòng)模式和 taskAffinity 屬性詳解

這里我們新建一個(gè) Activity B ,調(diào)用 Activity 流程 :A - A - B - A

  
   
override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_a)
        printTaskInfo(this, "onCreate")
    }

    override fun onNewIntent(intent: Intent?) {
        super.onNewIntent(intent)
        printTaskInfo(this, "onNewIntent")
    }

    override fun onStart() {
        super.onStart()
        printTaskInfo(this, "onStart")
    }

     fun click(view: View?) {
        when (view?.id) {
            R.id.bt_toA -> toActivity()
            R.id.bt_toB -> toActivity()
            else -> { }
        }
    }

打印日志:

01-02 22:15:18.399 28530-28530/com.will.testdemo I/debugLog: launchmode.A onCreate taskId = 45
01-02 22:15:18.400 28530-28530/com.will.testdemo I/debugLog: launchmode.A onStart taskId = 45
01-02 22:15:21.229 28530-28530/com.will.testdemo I/debugLog: launchmode.A onNewIntent taskId = 45
01-02 22:15:24.927 28530-28530/com.will.testdemo I/debugLog: launchmode.B onCreate taskId = 45
01-02 22:15:24.929 28530-28530/com.will.testdemo I/debugLog: launchmode.B onStart taskId = 45
01-02 22:15:26.449 28530-28530/com.will.testdemo I/debugLog: launchmode.A onCreate taskId = 45
01-02 22:15:26.450 28530-28530/com.will.testdemo I/debugLog: launchmode.A onStart taskId = 45

Activity Task 棧
Activity 啟動(dòng)模式和 taskAffinity 屬性詳解

可以看出當(dāng) A 在當(dāng)前棧頂?shù)臅r(shí)候沒有創(chuàng)建新的實(shí)例,并調(diào)用 onNewIntent 方法,沒有調(diào)用 onCreate 和 onStart 方法

singleTask 棧內(nèi)復(fù)用模式

這是一種單實(shí)例模式,在這種模式下,只要 Activity 在一個(gè)棧中存在,那么多次啟動(dòng)此 Activity 都不會(huì)重新創(chuàng)建實(shí)例,和 singleTop一樣,系統(tǒng)也會(huì)回調(diào)其 onNewIntent。當(dāng)一個(gè)具有 singleTask 模式的Activity請(qǐng)求啟動(dòng)后,比如 Activity A,系統(tǒng)首先會(huì)尋找是否存在 A 想要的任務(wù)棧,如果不存在,就重新創(chuàng)建一個(gè)任務(wù)棧,然后創(chuàng)建 A 的實(shí)例后把 A 放到棧中。如果存在 A 所需的任務(wù)棧,這時(shí)要看 A 是否在棧中有實(shí)例存在,如果有實(shí)例存在,那么系統(tǒng)就會(huì)把 A 調(diào)到棧頂并調(diào)用它的 onNewIntent 方法,如果實(shí)例不存在,就創(chuàng)建 A 的實(shí)例并把 A 壓入棧中 。

Activity 啟動(dòng)模式和 taskAffinity 屬性詳解

關(guān)于上文中所說的想要的任務(wù)棧,指的是 taskAffinity 屬性,手動(dòng)設(shè)置所需的任務(wù)棧,這個(gè)后面會(huì)具體介紹

調(diào)用 Activity 流程 依舊是:A - A - B - A
打印日志:

01-02 22:25:59.608 24498-24498/com.will.testdemo I/debugLog: launchmode.A onCreate taskId = 54
01-02 22:25:59.611 24498-24498/com.will.testdemo I/debugLog: launchmode.A onStart taskId = 54
01-02 22:26:02.844 24498-24498/com.will.testdemo I/debugLog: launchmode.A onNewIntent taskId = 54
01-02 22:26:05.753 24498-24498/com.will.testdemo I/debugLog: launchmode.B onCreate taskId = 54
01-02 22:26:05.758 24498-24498/com.will.testdemo I/debugLog: launchmode.B onStart taskId = 54
01-02 22:26:07.040 24498-24498/com.will.testdemo I/debugLog: launchmode.A onNewIntent taskId = 54
01-02 22:26:07.047 24498-24498/com.will.testdemo I/debugLog: launchmode.A onStart taskId = 54

Activity Task 棧
Activity 啟動(dòng)模式和 taskAffinity 屬性詳解

納尼 Activity B 呢 怎么不見了,這是什么鬼操作,原來是 singleTask 默認(rèn)有 clearTop 的效果,會(huì)導(dǎo)致棧內(nèi)所有在它上面的 Activity 全部出棧,這點(diǎn)一定不要忽略了

singleInstance 單實(shí)例模式

與 singleTask 相同,只是系統(tǒng)不會(huì)將任何其他 Activity 啟動(dòng)到包含實(shí)例的任務(wù)中。該 Activity 始終是其任務(wù)唯一僅有的成員;由此 Activity 啟動(dòng)的任何 Activity 均在單獨(dú)的任務(wù)中打開。也就是有此種模式的 Activity 只能單獨(dú)地位于一個(gè)任務(wù)棧中

調(diào)用 Activity 流程 :A - B - B - A,這次把 B 的啟動(dòng)模式設(shè)置為 singleInstance

打印日志:

01-02 22:41:59.069 305-305/com.will.testdemo I/debugLog: launchmode.A onCreate taskId = 57
01-02 22:41:59.071 305-305/com.will.testdemo I/debugLog: launchmode.A onStart taskId = 57
01-02 22:42:00.280 305-305/com.will.testdemo I/debugLog: launchmode.B onCreate taskId = 58
01-02 22:42:00.283 305-305/com.will.testdemo I/debugLog: launchmode.B onStart taskId = 58
01-02 22:42:02.340 305-305/com.will.testdemo I/debugLog: launchmode.B onNewIntent taskId = 58
01-02 22:42:03.658 305-305/com.will.testdemo I/debugLog: launchmode.A onCreate taskId = 57
01-02 22:42:03.659 305-305/com.will.testdemo I/debugLog: launchmode.A onStart taskId = 57

Activity Task 棧
Activity 啟動(dòng)模式和 taskAffinity 屬性詳解

結(jié)合打印日志和 Activity Task 棧可以看出,有此種模式的 Activity 只能單獨(dú)地位于一個(gè)任務(wù)棧中,如果已經(jīng)創(chuàng)建過,則調(diào)用 onNewIntent 方法 不會(huì)調(diào)用 onCreate 和 onStart

taskAffinity 屬性

taskAffinity,可以翻譯為任務(wù)相關(guān)性。這個(gè)參數(shù)標(biāo)識(shí)了一個(gè) Activity 所需要的任務(wù)棧的名字,默認(rèn)情況下,所有 Activity 所需的任務(wù)棧的名字為應(yīng)用的包名,當(dāng) Activity 設(shè)置了 taskAffinity 屬性,那么這個(gè) Activity 在被創(chuàng)建時(shí)就會(huì)運(yùn)行在和 taskAffinity 名字相同的任務(wù)棧中,如果沒有,則新建 taskAffinity 指定的任務(wù)棧,并將 Activity 放入該棧中。另外,taskAffinity 屬性主要和 singleTask 或者 allowTaskReparenting 屬性配對(duì)使用,在其他情況下沒有意義。

與 singleTask 結(jié)合使用,調(diào)用 Activity 流程:A - B - B - A - B,設(shè)置 B 的啟動(dòng)模式為 singleTask ,并設(shè)置 taskAffinity

    
        

     
        

打印日志:

01-02 23:13:29.179 16793-16793/com.will.testdemo I/debugLog: launchmode.A onCreate taskId = 59
01-02 23:13:29.180 16793-16793/com.will.testdemo I/debugLog: launchmode.A onStart taskId = 59
01-02 23:13:31.800 16793-16793/com.will.testdemo I/debugLog: launchmode.B onCreate taskId = 60
01-02 23:13:31.801 16793-16793/com.will.testdemo I/debugLog: launchmode.B onStart taskId = 60
01-02 23:13:33.740 16793-16793/com.will.testdemo I/debugLog: launchmode.B onNewIntent taskId = 60
01-02 23:13:34.928 16793-16793/com.will.testdemo I/debugLog: launchmode.A onCreate taskId = 60
01-02 23:13:34.931 16793-16793/com.will.testdemo I/debugLog: launchmode.A onStart taskId = 60
01-02 23:13:36.203 16793-16793/com.will.testdemo I/debugLog: launchmode.B onNewIntent taskId = 60
01-02 23:13:36.204 16793-16793/com.will.testdemo I/debugLog: launchmode.B onStart taskId = 60

Activity Task 棧
Activity 啟動(dòng)模式和 taskAffinity 屬性詳解

B 被創(chuàng)建時(shí),因沒有 com.will.testdemo.task1 的任務(wù)棧,于是新建任務(wù)棧,并把 B 放入棧內(nèi)。繼續(xù)創(chuàng)建 A,由于 A 沒有設(shè)置啟動(dòng)模式,則放入 com.will.testdemo.task1 棧中。再一次啟動(dòng) B,因棧內(nèi)有 B 實(shí)例,所以系統(tǒng)就把 B 調(diào)到棧頂,由于 singleTask 默認(rèn)有 clearTop 的效果,導(dǎo)致棧內(nèi)所有在它上面的 Activity 全部出棧,所以最后 com.will.testdemo.task1 棧內(nèi)只有 B 一個(gè)實(shí)例

總結(jié)

上面廢話了那么多,那么這些啟動(dòng)模式到底什么時(shí)候使用呢,這里列出部分使用場景以供參考。

launchMode使用場景
singleTop 適合啟動(dòng)同類型的 Activity,例如接收通知啟動(dòng)的內(nèi)容顯示頁面
singleTask 適合作為程序入口
singleInstance 適合需要與程序分離開的頁面,例如鬧鈴的響鈴界面

分享名稱:Activity啟動(dòng)模式和taskAffinity屬性詳解
轉(zhuǎn)載來源:
http://weahome.cn/article/ggsejj.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部