1. 程式人生 > >基礎總結篇之二:Activity的四種launchMode

基礎總結篇之二:Activity的四種launchMode

合抱之木,生於毫末;九層之臺,起於累土;千里之行,始於足下。《老子》

今天在社群看到有朋友問“如何在半年內成為頂級架構師”,有網友道“關燈睡覺,不用半年的...”,的確,做夢還來的快一些。作為一個程式設計師,樹立遠大的目標是值得欣賞的,但不能只去空想,要一步一步地實踐才行。成大事者,須從小事做起;萬事起於忽微,量變引起質變。

我們今天要講的是Activity的四種launchMode。

launchMode在多個Activity跳轉的過程中扮演著重要的角色,它可以決定是否生成新的Activity例項,是否重用已存在的Activity例項,是否和其他Activity例項公用一個task裡。這裡簡單介紹一下task的概念,task是一個具有棧結構的物件,一個task可以管理多個Activity,啟動一個應用,也就建立一個與之對應的task。

Activity一共有以下四種launchMode:

1.standard

2.singleTop

3.singleTask

4.singleInstance

我們可以在AndroidManifest.xml配置<activity>的Android:launchMode屬性為以上四種之一即可。

下面我們結合例項一一介紹這四種lanchMode:

1.standard

standard模式是預設的啟動模式,不用為<activity>配置android:launchMode屬性即可,當然也可以指定值為standard。

我們將會一個Activity,命名為FirstActivity,來演示一下標準的啟動模式。FirstActivity程式碼如下:

  1. package com.scott.launchmode;  
  2. import android.app.Activity;  
  3. import android.content.Intent;  
  4. import android.os.Bundle;  
  5. import android.view.View;  
  6. import android.widget.Button;  
  7. import android.widget.TextView;  
  8. publicclass FirstActivity extends Activity {  
  9.     @Override
  10.     publicvoid onCreate(Bundle savedInstanceState) {  
  11.         super.onCreate(savedInstanceState);  
  12.         setContentView(R.layout.first);  
  13.         TextView textView = (TextView) findViewById(R.id.textView);  
  14.         textView.setText(this.toString());  
  15.         Button button = (Button) findViewById(R.id.button);  
  16.         button.setOnClickListener(new View.OnClickListener() {  
  17.             @Override
  18.             publicvoid onClick(View v) {  
  19.                 Intent intent = new Intent(FirstActivity.this, FirstActivity.class);  
  20.                 startActivity(intent);  
  21.             }  
  22.         });  
  23.     }  
  24. }  
我們FirstActivity介面中的TextView用於顯示當前Activity例項的序列號,Button用於跳轉到下一個FirstActivity介面。

然後我們連續點選幾次按鈕,將會出現下面的現象:

我們注意到都是FirstActivity的例項,但序列號不同,並且我們需要連續按後退鍵兩次,才能回到第一個FristActivity。standard模式的原理如下圖所示:


如圖所示,每次跳轉系統都會在task中生成一個新的FirstActivity例項,並且放於棧結構的頂部,當我們按下後退鍵時,才能看到原來的FirstActivity例項。

這就是standard啟動模式,不管有沒有已存在的例項,都生成新的例項。

2.singleTop

我們在上面的基礎上為<activity>指定屬性android:launchMode="singleTop",系統就會按照singleTop啟動模式處理跳轉行為。我們重複上面幾個動作,將會出現下面的現象:




我們看到這個結果跟standard有所不同,三個序列號是相同的,也就是說使用的都是同一個FirstActivity例項;如果按一下後退鍵,程式立即退出,說明當前棧結構中只有一個Activity例項。singleTop模式的原理如下圖所示:


正如上圖所示,跳轉時系統會先在棧結構中尋找是否有一個FirstActivity例項正位於棧頂,如果有則不再生成新的,而是直接使用。也許朋友們會有疑問,我只看到棧內只有一個Activity,如果是多個Activity怎麼辦,如果不是在棧頂會如何?我們接下來再通過一個示例來證實一下大家的疑問。

我們再新建一個Activity命名為SecondActivity,如下:

  1. package com.scott.launchmode;  
  2. import android.app.Activity;  
  3. import android.content.Intent;  
  4. import android.os.Bundle;  
  5. import android.view.View;  
  6. import android.widget.Button;  
  7. import android.widget.TextView;  
  8. publicclass SecondActivity extends Activity {  
  9.     @Override
  10.     protectedvoid onCreate(Bundle savedInstanceState) {  
  11.         super.onCreate(savedInstanceState);  
  12.         setContentView(R.layout.second);  
  13.         TextView textView = (TextView) findViewById(R.id.textView);  
  14.         textView.setText(this.toString());  
  15.         Button button = (Button) findViewById(R.id.button);  
  16.         button.setOnClickListener(new View.OnClickListener() {  
  17.             @Override
  18.             publicvoid onClick(View v) {  
  19.                 Intent intent = new Intent(SecondActivity.this, FirstActivity.class);  
  20.                 startActivity(intent);                
  21.             }  
  22.         });  
  23.     }  
  24. }  
然後將之前的FirstActivity跳轉程式碼改為:
  1. Intent intent = new Intent(FirstActivity.this, SecondActivity.class);  
  2. startActivity(intent);  
是的,FirstActivity會跳轉到SecondActivity,SecondActivity又會跳轉到FirstActivity。演示結果如下:




我們看到,兩個FirstActivity的序列號是不同的,證明從SecondActivity跳轉到FirstActivity時生成了新的FirstActivity例項。原理圖如下:


我們看到,當從SecondActivity跳轉到FirstActivity時,系統發現存在有FirstActivity例項,但不是位於棧頂,於是重新生成一個例項。

這就是singleTop啟動模式,如果發現有對應的Activity例項正位於棧頂,則重複利用,不再生成新的例項。

3.singleTask

在上面的基礎上我們修改FirstActivity的屬性android:launchMode="singleTask"。演示的結果如下:



我們注意到,在上面的過程中,FirstActivity的序列號是不變的,SecondActivity的序列號卻不是唯一的,說明從SecondActivity跳轉到FirstActivity時,沒有生成新的例項,但是從FirstActivity跳轉到SecondActivity時生成了新的例項。singleTask模式的原理圖如下圖所示:


在圖中的下半部分是SecondActivity跳轉到FirstActivity後的棧結構變化的結果,我們注意到,SecondActivity消失了,沒錯,在這個跳轉過程中系統發現有存在的FirstActivity例項,於是不再生成新的例項,而是將FirstActivity之上的Activity例項統統出棧,將FirstActivity變為棧頂物件,顯示到幕前。也許朋友們有疑問,如果將SecondActivity也設定為singleTask模式,那麼SecondActivity例項是不是可以唯一呢?在我們這個示例中是不可能的,因為每次從SecondActivity跳轉到FirstActivity時,SecondActivity例項都被迫出棧,下次等FirstActivity跳轉到SecondActivity時,找不到存在的SecondActivity例項,於是必須生成新的例項。但是如果我們有ThirdActivity,讓SecondActivity和ThirdActivity互相跳轉,那麼SecondActivity例項就可以保證唯一。

這就是singleTask模式,如果發現有對應的Activity例項,則使此Activity例項之上的其他Activity例項統統出棧,使此Activity例項成為棧頂物件,顯示到幕前。

4.singleInstance

這種啟動模式比較特殊,因為它會啟用一個新的棧結構,將Acitvity放置於這個新的棧結構中,並保證不再有其他Activity例項進入。

我們修改FirstActivity的launchMode="standard",SecondActivity的launchMode="singleInstance",由於涉及到了多個棧結構,我們需要在每個Activity中顯示當前棧結構的id,所以我們為每個Activity新增如下程式碼:

  1. TextView taskIdView = (TextView) findViewById(R.id.taskIdView);  
  2. taskIdView.setText("current task id: " + this.getTaskId());  
然後我們再演示一下這個流程:


我們發現這兩個Activity例項分別被放置在不同的棧結構中,關於singleInstance的原理圖如下:


我們看到從FirstActivity跳轉到SecondActivity時,重新啟用了一個新的棧結構,來放置SecondActivity例項,然後按下後退鍵,再次回到原始棧結構;圖中下半部分顯示的在SecondActivity中再次跳轉到FirstActivity,這個時候系統會在原始棧結構中生成一個FirstActivity例項,然後回退兩次,注意,並沒有退出,而是回到了SecondActivity,為什麼呢?是因為從SecondActivity跳轉到FirstActivity的時候,我們的起點變成了SecondActivity例項所在的棧結構,這樣一來,我們需要“迴歸”到這個棧結構。

如果我們修改FirstActivity的launchMode值為singleTop、singleTask、singleInstance中的任意一個,流程將會如圖所示:

singleInstance啟動模式可能是最複雜的一種模式,為了幫助大家理解,我舉一個例子,假如我們有一個share應用,其中的ShareActivity是入口Activity,也是可供其他應用呼叫的Activity,我們把這個Activity的啟動模式設定為singleInstance,然後在其他應用中呼叫。我們編輯ShareActivity的配置:

  1. <activityandroid:name=".ShareActivity"android:launchMode="singleInstance">
  2.     <intent-filter>
  3.         <actionandroid:name="android.intent.action.MAIN"/>
  4.         <categoryandroid:name="android.intent.category.LAUNCHER"/>
  5.     </intent-filter>
  6.     <intent-filter>
  7.         <actionandroid:name="android.intent.action.SINGLE_INSTANCE_SHARE"/>
  8.         <categoryandroid:name="android.intent.category.DEFAULT"/>
  9.     </intent-filter>
  10. </activity>
然後我們在其他應用中這樣啟動該Activity:
  1. Intent intent = new Intent("android.intent.action.SINGLE_INSTANCE_SHARE");  
  2. startActivity(intent);  
當我們開啟ShareActivity後再按後退鍵回到原來介面時,ShareActivity做為一個獨立的個體存在,如果這時我們開啟share應用,無需建立新的ShareActivity例項即可看到結果,因為系統會自動查詢,存在則直接利用。大家可以在ShareActivity中列印一下taskId,看看效果。關於這個過程,原理圖如下:

相關推薦

基礎總結ActivitylaunchMode

合抱之木,生於毫末;九層之臺,起於累土;千里之行,始於足下。《老子》 今天在社群看到有朋友問“如何在半年內成為頂級架構師”,有網友道“關燈睡覺,不用半年的...”,的確,做夢還來的快一些。作為一個程式設計師,樹立遠大的目標是值得欣賞的,但不能只去空想,要一步一步地實踐

基礎總結ContentProvider讀寫聯絡人

靡不有初,鮮克有終。《詩經》 很多事情,絕大多數人都會在開始的時候滿懷熱情,而能堅持到底的卻是寥寥無幾。對待自己的目標,虎頭蛇尾絕不可取,半途而廢只會一無所成,我們必須持之以恆的做下去,堅持到底才能摘取勝利的果實。最近也忙了起來,忙著給自己充電,深知這項任務的艱鉅,不是一天

列聯表格表的分析

轉載出處:https://zhuanlan.zhihu.com/p/27312651 在列聯表中,二維表是最基礎的一類表,在二維表中,四格表是最基礎的一類表。 下面針對表格資料的各種不同形式來介紹相應的分析方法。基本四格表的分析方法1.正態近似 基本四格表其實

UVM序列sequence和item(上)

技術 一點 目標 idt 需要 開始 掛載 ron 前行 無論是自駕item,穿過sequencer交通站,通往終點driver,還是坐上sequence的大巴,一路沿途觀光,最終跟隨導遊停靠到風景點driver,在介紹如何駕駛item和sequence,遵守什麽交規,最終

UVM暫存器暫存器模型概覽(下)

本文轉自:http://www.eetop.cn/blog/html/28/1561828-6266219.html 暫存器模型構建 在構建UVM暫存器模型的過程中,讀者需要了解下面這些與模型構建相關的類和它們的功能:     簡化後的MCDF暫存器模

C#基礎拾遺系列使用ILSpy探索C#7.0新增功能點

第一部分: C#是一種通用的,型別安全的,面向物件的程式語言。有如下特點: (1)面向物件:c# 是面向物件的範例的一個豐富實現, 它包括封裝、繼承和多型性。C#面向物件的行為包括: 統一的型別系統 類與介面 屬性、方法、事件 (2)型別安全:C#還允許通過dynamic關鍵字動態

影象處理基礎知識系列核概率密度估計簡介

  在這裡提出一個問題,假設資料不完整性一致,就是x我們不知道的取值數量是一定的,最後的概率密度估計圖形和什麼有關係呢?和bin有關。bin不同,最後的對應著概率密度估計就不同,如圖5和圖6。這個bin組距引數對應著公式(1)中的h,,,而公式(1)中的n對應著直方圖組數,(組距=bin=h,組數=n)具體關

Android入門Activity啟動模式

一、啟動模式介紹   啟動模式簡單地說就是Activity啟動時的策略,在AndroidManifest.xml中的標籤的android:launchMode屬性設定;   啟動模式有4種,分別為standard、singleTop、singleTask、singleInstance; 講解啟動模式之前

基礎總結ContentProvider讀寫聯絡人

靡不有初,鮮克有終。《詩經》 很多事情,絕大多數人都會在開始的時候滿懷熱情,而能堅持到底的卻是寥寥無幾。對待自己的目標,虎頭蛇尾絕不可取,半途而廢只會一無所成,我們必須持之以恆的做下去,堅持到底才能摘取勝利的果實。最近也忙了起來,忙著給自己充電,深知這項任務的艱鉅,不是一天兩天的事,所以也借用這句警言來告誡

linux學習日常的基礎命令收集

幫助文檔 gedit 查看 日期 取整 style 位置 某月 linux 1、 ls 2、pwd  顯示當前目錄所在位置 3、date  日期時間 4、cal  日歷   默認顯示當前該月   cal 2012 :查看2012年的日歷   cal 月 年 : 查看某年某月

Lucene學習總結Lucene的總體架構

api 要點 iter 不同 blank 應用 文件 score image Lucene總的來說是: 一個高效的,可擴展的,全文檢索庫。 全部用Java實現,無須配置。 僅支持純文本文件的索引(Indexing)和搜索(Search)。 不負責由其他格式的文件抽取純文

React總結_模組化React和Redux應用

建立一個複雜一點的應用應該如何做: 模組化應用的要點 程式碼檔案的組織方式 狀態數的設計 開發輔助工具 一、模組化應用的要點1.構建一個應用的基礎要做如下3件事情: 程式碼檔案的組織結構 確定模組的邊界 store的狀態樹設計 程式碼檔案的組織方式:按功

資料結構實驗叉樹(先序中序)還原叉樹 (SDUT 3343)

#include <bits/stdc++.h> using namespace std; struct node { char data; struct node *lc, *rc; }; char a[100],b[100]; int n; struct node

5.2 SpringBoot實現斷點續傳功能 > 我的程式猿

  功能使用webuploader元件分片下載檔案 文件地址: http://fex.baidu.com/webuploader/document.html 從  http://fex.baidu.com/webuploader/download.html中下載 用到的是:

[知乎]老狼:深入PCI與PCIe軟體

  深入PCI與PCIe之二:軟體篇 https://zhuanlan.zhihu.com/p/26244141 我們前一篇文章( 深入PCI與PCIe之一:硬體篇 - 知乎專欄)介紹了PCI和PCIe的硬體部分。本篇主要介紹PCI和PCIe的軟體介面和UEFI對P

keyguard分析息屏與亮屏流程

息屏與亮屏時, Keyguard繪製的基本流程   手機的Power鍵在滅屏是會載入keyguard, 保證使用者在亮屏時,第一時間看到鎖屏介面,以保證使用者的良好體驗. 在亮屏過程中涉及到了兩條主要的執行緒: PowerManager Thread 和DisplayMa

【U3D效能優化教程——CPU靜態批處理&靜態批處理

這篇文章由唐三胖ヾ(•ω•`)o網路整理總結,針對DrawCall概念的系列優化教程。 通過這篇文章,你可以知道 1)動態/靜態批處理的概念 2)什麼時候會動態批

【U3D系統架構教程——開發Log日誌系統2.0

這篇文章由唐三胖ヾ(•ω•`)o網路整理總結,將告訴你如何開發一個高效率的日誌系統。 通過這篇文章,你可以知道 1)C#特性Condtional 2)開發2.0版的日誌系統 開篇介紹 通過上一章節的介紹,我們已經實現了重寫的日誌

資料結構實驗叉樹(先序中序)還原叉樹

Problem Description 給定一棵二叉樹的先序遍歷序列和中序遍歷序列,要求計算該二叉樹的高度。 Input 輸入資料有多組,每組資料第一行輸入1個正整數N(1 <= N <=

Redis大總結Redis 事務,WATCH命令,生存時間

事務 Ø  MULTI,EXEC操作:事務的開始和結束標記 n 執行Multi命令,redis反饋ok表示開始事務;執行EXEC命令,結束事務,開始順序執行事務中的操作。 127.0.0.1:6379[5]> MULTI OK 127.0.0.1:6379[5]&g