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

資訊專欄INFORMATION COLUMN

Android 啟動模式--任務(Task)--桟 的誤區

894974231 / 2810人閱讀

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

Android 啟動模式--任務(Task)--桟 的誤區

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

概念

桟(堆棧:stack)

棧的基本特點:

先入后出,后入先出。

除頭尾節點之外,每個元素有一個前驅,一個后繼。

任務

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

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

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

個人理解

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

Activity 四大啟動模式

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

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

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

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

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

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

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

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

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

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

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

關于android:taskAffinity屬性
android:taskAffinity

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

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

測試 SingleTaskSingleInstance的異同

我寫了一個Demo測試了下:

當我把SingleTaskA配置為:

SingleTaskA中啟動一個標準模式的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";
    }
}

補充下基類:

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();
}

得到如下結果:

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啟動了一個新的任務(Task),id為27,之后在SingleTaskA中啟動StandardB并沒有做其他的操作,而是直接在剛剛SingleTaskA啟動的任務中添加.

現在我去掉 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

可見,默認是不會創建新的任務的.

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

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新建了一個任務id為31,在 SingleInstanceA 中啟動 StandardB 還是繼續添加在之前任務中.

總結:

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

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

SingleTask默認不會創建新任務,但是可以通過taskAffinity達到創建新任務的目的,創建的任務可添加其他元素.

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

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/66814.html

相關文章

發表評論

0條評論

894974231

|高級講師

TA的文章

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