国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Android 啟動模式--任務(wù)(Task)--桟 的誤區(qū)

894974231 / 2816人閱讀

摘要:如果具有默認(rèn)的啟動模式,則會啟動該類的新實例,且堆棧會變成。但是,如果的啟動模式是,則的現(xiàn)有實例會通過接收,因為它位于堆棧的頂部而堆棧仍為。上圖顯示如何將啟動模式為的添加到返回棧。任務(wù)的親和關(guān)系由其根的親和關(guān)系確定。

Android 啟動模式--任務(wù)(Task)--桟 的誤區(qū)

寫這篇文章是因為前幾天的一次面試,面試官說SingleInstance模式會新建一個桟,而SingleTask不會.首先不說這個對不對(非要說對錯的話,那就是錯.),因為這句話是含糊不清的.?只的是返回桟? 還是任務(wù)桟?有沒有考慮taskAffinity屬性?所以籠統(tǒng)的那樣說是不對的.這篇文章一是為了記錄,二是為了說清楚----任務(wù)(Task)& 桟(返回桟,任務(wù)桟).

概念

桟(堆棧:stack)

棧的基本特點:

先入后出,后入先出。

除頭尾節(jié)點之外,每個元素有一個前驅(qū),一個后繼。

任務(wù)

任務(wù)是指在執(zhí)行特定作業(yè)時與用戶交互的一系列 Activity。 這些 Activity 按照各自的打開順序排列在堆棧(即返回棧)中。

返回桟
在官方文檔中,找不到關(guān)于返回桟的概念,但是按照官方文檔在描述時的語境,可以理解為響應(yīng)Android返回鍵的順序隊列.這是站在用戶的直觀感受上的描述.Android 內(nèi)部的描述單位只有任務(wù)(Task).

任務(wù)桟
在官方文檔中沒有這個概念.我為了方便理解,把任務(wù)中按照規(guī)則的順序隊列的 一系列 Activity 稱為 任務(wù)棧.

個人理解

由于 官方文檔中沒有詳細(xì)的說明什么是返回桟,在實際的開發(fā)中如果以棧為基本度量單位的話,很容易被自己繞暈,如果按照任務(wù)為基本度量單位的話就很容易理清楚 Android 四大啟動模式了.我個人把返回棧理解為這樣子的: 返回桟僅有一個(因為返回鍵只有一個),返回桟操作的基本元素是任務(wù),返回鍵操作的是返回桟中處于前臺的任務(wù),每個任務(wù)維護(hù)著一系列 Activity 組成的以響應(yīng)返回鍵.

Activity 四大啟動模式

"standard"(默認(rèn)模式)
默認(rèn)。系統(tǒng)在啟動 Activity 的任務(wù)中創(chuàng)建 Activity 的新實例并向其傳送 Intent。Activity 可以多次實例化,而每個實例均可屬于不同的任務(wù),并且一個任務(wù)可以擁有多個實例。

"singleTop"
如果當(dāng)前任務(wù)的頂部已存在 Activity 的一個實例,則系統(tǒng)會通過調(diào)用該實例的 onNewIntent() 方法向其傳送 Intent,而不是創(chuàng)建 Activity 的新實例。Activity 可以多次實例化,而每個實例均可屬于不同的任務(wù),并且一個任務(wù)可以擁有多個實例(但前提是位于返回棧頂部的 Activity 并不是 Activity 的現(xiàn)有實例)。

例如,假設(shè)任務(wù)的返回棧包含根 Activity A 以及 Activity B、C 和位于頂部的 D(堆棧是 A-B-C-D;D 位于頂部)。收到針對 D 類 Activity 的 Intent。如果 D 具有默認(rèn)的 "standard" 啟動模式,則會啟動該類的新實例,且堆棧會變成 A-B-C-D-D。但是,如果 D 的啟動模式是"singleTop",則 D 的現(xiàn)有實例會通過 onNewIntent() 接收 Intent,因為它位于堆棧的頂部;而堆棧仍為 A-B-C-D。但是,如果收到針對 B 類 Activity 的 Intent,則會向堆棧添加 B 的新實例,即便其啟動模式為 "singleTop" 也是如此。

注:為某個 Activity 創(chuàng)建新實例時,用戶可以按“返回”按鈕返回到前一個 Activity。 但是,當(dāng) Activity 的現(xiàn)有實例處理新 Intent 時,則在新 Intent 到達(dá) onNewIntent() 之前,用戶無法按“返回”按鈕返回到 Activity 的狀態(tài)。

"singleTask"
系統(tǒng)創(chuàng)建新任務(wù)并實例化位于新任務(wù)底部的 Activity。但是,如果該 Activity 的一個實例已存在于一個多帶帶的任務(wù)中,則系統(tǒng)會通過調(diào)用現(xiàn)有實例的 onNewIntent() 方法向其傳送 Intent,而不是創(chuàng)建新實例。一次只能存在 Activity 的一個實例。

注:盡管 Activity 在新任務(wù)中啟動,但是用戶按“返回”按鈕仍會返回到前一個 Activity。

"singleInstance".
與 "singleTask" 相同,只是系統(tǒng)不會將任何其他 Activity 啟動到包含實例的任務(wù)中。該 Activity 始終是其任務(wù)唯一僅有的成員;由此 Activity 啟動的任何 Activity 均在多帶帶的任務(wù)中打開。

我們再來看另一示例,Android 瀏覽器應(yīng)用聲明網(wǎng)絡(luò)瀏覽器 Activity 應(yīng)始終在其自己的任務(wù)中打開(通過在 元素中指定 singleTask 啟動模式)。這意味著,如果您的應(yīng)用發(fā)出打開 Android 瀏覽器的 Intent,則其 Activity 與您的應(yīng)用位于不同的任務(wù)中。相反,系統(tǒng)會為瀏覽器啟動新任務(wù),或者如果瀏覽器已有任務(wù)正在后臺運(yùn)行,則會將該任務(wù)上移一層以處理新 Intent。

無論 Activity 是在新任務(wù)中啟動,還是在與啟動 Activity 相同的任務(wù)中啟動,用戶按“返回”按鈕始終會轉(zhuǎn)到前一個 Activity。 但是,如果啟動指定 singleTask 啟動模式的 Activity,則當(dāng)某后臺任務(wù)中存在該 Activity 的實例時,整個任務(wù)都會轉(zhuǎn)移到前臺。此時,返回棧包括上移到堆棧頂部的任務(wù)中的所有 Activity。 上圖顯示了這種情況。

上圖 顯示如何將啟動模式為“singleTask”的 Activity 添加到返回棧。 如果 Activity 已經(jīng)是某個擁有自己的返回棧的后臺任務(wù)的一部分,則整個返回棧也會上移到當(dāng)前任務(wù)的頂部。

參考:2017-03-14日摘自官方文檔(后期可能有變更以官網(wǎng)為準(zhǔn))

關(guān)于android:taskAffinity屬性
android:taskAffinity

與 Activity 有著親和關(guān)系的任務(wù)。從概念上講,具有相同親和關(guān)系的 Activity 歸屬同一任務(wù)(從用戶的角度來看,則是歸屬同一“應(yīng)用”)。 任務(wù)的親和關(guān)系由其根 Activity 的親和關(guān)系確定。
親和關(guān)系確定兩件事 - Activity 更改到的父項任務(wù)(請參閱 allowTaskReparenting 屬性)和通過 FLAG_ACTIVITY_NEW_TASK 標(biāo)志啟動 Activity 時將用來容納它的任務(wù)。
默認(rèn)情況下,應(yīng)用中的所有 Activity 都具有相同的親和關(guān)系。您可以設(shè)置該屬性來以不同方式組合它們,甚至可以將在不同應(yīng)用中定義的 Activity 置于同一任務(wù)內(nèi)。 要指定 Activity 與任何任務(wù)均無親和關(guān)系,請將其設(shè)置為空字符串。
如果未設(shè)置該屬性,則 Activity 繼承為應(yīng)用設(shè)置的親和關(guān)系(請參閱 元素的 taskAffinity 屬性)。 應(yīng)用默認(rèn)親和關(guān)系的名稱是 元素設(shè)置的軟件包名稱。

參考:2017-03-14日摘自官方文檔(后期可能有變更以官網(wǎng)為準(zhǔn))

測試 SingleTaskSingleInstance的異同

我寫了一個Demo測試了下:

當(dāng)我把SingleTaskA配置為:

SingleTaskA中啟動一個標(biāo)準(zhǔn)模式的StandardBActivity:

public class SingleTaskA extends BaseLauncherModeActivity {
    @Override
    protected Class gotoActivity() {
        return StandardB.class;
    }

    @Override
    protected String setModeTextShow() {
        return Constant.SINGLE_TASK;
    }
}

而在StandardB中,我一直啟動StandardB自己:

public class StandardB extends BaseLauncherModeActivity {
    @Override
    protected Class gotoActivity() {
        return StandardB.class;
    }

    @Override
    protected String setModeTextShow() {
        return Constant.STANDARD+"Repeat";
    }
}

補(bǔ)充下基類:

public abstract class BaseLauncherModeActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_base_launcher_mode);
        String text = setModeTextShow();
        Button button = (Button) findViewById(R.id.bt);
        button.setText("模式: "+text);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Class aClass = gotoActivity();
                if (aClass==null)return;
                startActivity(new Intent(getApplicationContext(),aClass));
            }
        });
        int taskId = getTaskId();
        Log.d(Constant.TAG,"taskId: "+taskId);
    }

    protected abstract Class gotoActivity();

    protected abstract String setModeTextShow();
}

得到如下結(jié)果:

03-14 10:32:32.287 22561-22561/com.didikee.androidlaunchermode D/AndroidLauncherMode: taskId: 26
03-14 10:32:37.691 22561-22561/com.didikee.androidlaunchermode D/AndroidLauncherMode: taskId: 26
03-14 10:32:42.120 22561-22561/com.didikee.androidlaunchermode D/AndroidLauncherMode: taskId: 27
03-14 10:32:45.961 22561-22561/com.didikee.androidlaunchermode D/AndroidLauncherMode: taskId: 27
03-14 10:32:52.105 22561-22561/com.didikee.androidlaunchermode D/AndroidLauncherMode: taskId: 27
03-14 10:32:53.531 22561-22561/com.didikee.androidlaunchermode D/AndroidLauncherMode: taskId: 27
03-14 10:32:55.748 22561-22561/com.didikee.androidlaunchermode D/AndroidLauncherMode: taskId: 27
03-14 10:32:56.763 22561-22561/com.didikee.androidlaunchermode D/AndroidLauncherMode: taskId: 27

可以看到,SingleTaskA啟動了一個新的任務(wù)(Task),id為27,之后在SingleTaskA中啟動StandardB并沒有做其他的操作,而是直接在剛剛SingleTaskA啟動的任務(wù)中添加.

現(xiàn)在我去掉 taskAffinity屬性的定義,得到:

03-14 16:42:10.604 31062-31062/com.didikee.androidlaunchermode D/AndroidLauncherMode: taskId: 29
03-14 16:42:15.261 31062-31062/com.didikee.androidlaunchermode D/AndroidLauncherMode: taskId: 29
03-14 16:42:16.865 31062-31062/com.didikee.androidlaunchermode D/AndroidLauncherMode: taskId: 29
03-14 16:42:19.197 31062-31062/com.didikee.androidlaunchermode D/AndroidLauncherMode: taskId: 29
03-14 16:42:20.232 31062-31062/com.didikee.androidlaunchermode D/AndroidLauncherMode: taskId: 29
03-14 16:42:21.049 31062-31062/com.didikee.androidlaunchermode D/AndroidLauncherMode: taskId: 29
03-14 16:42:22.180 31062-31062/com.didikee.androidlaunchermode D/AndroidLauncherMode: taskId: 29

可見,默認(rèn)是不會創(chuàng)建新的任務(wù)的.

現(xiàn)在,把SingleTaskA 改為 SingleInstanceA,然后在其中可以啟動StandardB(上面有代碼),得到如下結(jié)果:

03-14 16:46:59.669 2273-2273/com.didikee.androidlaunchermode D/AndroidLauncherMode: taskId: 30
03-14 16:47:09.367 2273-2273/com.didikee.androidlaunchermode D/AndroidLauncherMode: taskId: 30
03-14 16:47:10.602 2273-2273/com.didikee.androidlaunchermode D/AndroidLauncherMode: taskId: 31
03-14 16:47:12.013 2273-2273/com.didikee.androidlaunchermode D/AndroidLauncherMode: taskId: 30
03-14 16:47:14.438 2273-2273/com.didikee.androidlaunchermode D/AndroidLauncherMode: taskId: 30
03-14 16:47:15.429 2273-2273/com.didikee.androidlaunchermode D/AndroidLauncherMode: taskId: 30

可見,SingleInstanceA新建了一個任務(wù)id為31,在 SingleInstanceA 中啟動 StandardB 還是繼續(xù)添加在之前任務(wù)中.

總結(jié):

Android 是以任務(wù)為核心的,不要被棧帶偏了.

SingleInstance 一定會新建一個任務(wù),并且該任務(wù)中僅包含一個實例.

SingleTask默認(rèn)不會創(chuàng)建新任務(wù),但是可以通過taskAffinity達(dá)到創(chuàng)建新任務(wù)的目的,創(chuàng)建的任務(wù)可添加其他元素.

最后,說的不對的歡迎交流.

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/66814.html

相關(guān)文章

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<