最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

Android開發(fā)學習教程(24)- Android中Activity的啟動模式(LaunchMode)和使用場景

2023-01-28 14:57 作者:ChatGPT云炬學長  | 我要投稿

1、為何須要啟動模式
在Android開發(fā)中,咱們都知道,在默認的狀況下,若是咱們啟動的是同一個Activity的話,系統(tǒng)會建立多個實例并把它們一一放入任務棧中。當咱們點擊返回(back)鍵,這些Activity實例又將從任務棧中一一移除,遵循的原則是“后進先出”(先進后出)。android

這里咱們考慮一個問題,當咱們屢次啟動同一個Activity,系統(tǒng)也會建立多個實例放入任務棧中,這樣豈不是很耗費內存資源?為了解決這一問題,Android為Actiivty提供了啟動模式。shell

Activity的啟動模式有四種:standard、singleTop、singleTask和singleInstance。app

2、啟動模式的分類
一、standard:標準模式
這種啟動模式為標準模式,也是默認模式。每當咱們啟動一個Activity,系統(tǒng)就會相應的建立一個實例,無論這個實例是否已經存在。這種模式,一個棧中能夠有多個實例,每一個實例也都有本身的任務棧。并且是誰啟動了此Activity,那么這個Activity就運行在啟動它的Activity所在的棧中。ide

Manifest中配置:
對于標準模式,android:launchMode=”standard”能夠不寫,由于默認就是standard模式。
<activity
android:name=”.StandardActivity”
android:launchMode=”standard” >
</activity>

測試

使用案例:
MainActivity有一個按鈕,點擊按鈕會打開StandardActivity。打開StandardActivity也有一個按鈕,點擊也是啟動一個StandardActivity。而且咱們在onCreate()方法中打印TaskId和hashCode值。
打開步驟:MainActivity->StandardActivity->StandardActivity->StandardActivitythis

MainActivity:對象

public class MainActivity extends AppCompatActivity {內存

private static final String TAG = MainActivity.class.getSimpleName();資源

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_demo);開發(fā)

findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
StandardActivity.open(MainActivity.this);
}
});

Log.e(TAG, “———onCreate(): TaskId: ” + getTaskId() +”, hashCode: ” + hashCode());

}

}

StandardActivity :

/**
* 啟動模式:Standard(標準模式)
*/

public class StandardActivity extends AppCompatActivity {

private static final String TAG = StandardActivity.class.getSimpleName();

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_launch_mode);

findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
open(StandardActivity.this);
}
});

Log.e(TAG, “———onCreate(): TaskId: ” + getTaskId() +”, hashCode: ” + hashCode());
}

public static void open(Context context) {
context.startActivity(new Intent(context, StandardActivity.class));
}

}

控制臺打印log以下:

經過案例的log分析,能夠得出標準模式下,每當打開一次Activity就會建立一個新的實例,由于hashCode值都不一樣,并且都建立在啟動它的Activity所屬的任務棧中,也就是MainActivity所在的任務棧中,由于它們的任務棧Id一致。

分析總結:
標準模式下,只要啟動一次Activity,系統(tǒng)就會在當前任務棧新建一個實例。

使用場景:
正常的去打開一個新的頁面,這種啟動模式使用最多,最普通 。

二、singleTop:棧頂復用模式
這種啟動模式下,若是要啟動的Activity已經處于棧的頂部,那么此時系統(tǒng)不會建立新的實例,而是直接打開此頁面,同時它的onNewIntent()方法會被執(zhí)行,咱們能夠經過Intent進行傳值,并且它的onCreate(),onStart()方法不會被調用,由于它并無發(fā)生任何變化。

Manifest中配置:
<activity
android:name=”.SingleTopActivity”
android:launchMode=”singleTop”>
</activity>
1
2
3
4
使用案例:
MainActivity仍然是一個按鈕,點擊按鈕打開SingleTopActivity,SingleTopActivity有兩個按鈕,一個是打開SingleTopActivity,一個是打開OtherActivity,OtherActivity有一個按鈕,點擊按鈕能夠打開SingleTopActivity。并且咱們在onCreate()、onNewIntent()打印taskId和hashCode值。

打開步驟:MainActivity->SingleTopActivity->SingleTopActivity->OtherActivity->SingleTopActivity->SingleTopActivity

MainActivity:

public class MainActivity extends AppCompatActivity {

private static final String TAG = MainActivity.class.getSimpleName();

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_demo);

findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SingleTopActivity.open(MainActivity.this);
}
});

Log.e(TAG, “———onCreate(): TaskId: ” + getTaskId() +”, hashCode: ” + hashCode());

}

SingleTopActivity :

/**
* 啟動模式:棧頂復用模式
*/

public class SingleTopActivity extends AppCompatActivity {

private static final String TAG = SingleTopActivity.class.getSimpleName();

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_launch_mode);

findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
open(SingleTopActivity.this);
}
});
findViewById(R.id.btn_other).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
OtherActivity.open(SingleTopActivity.this);
}
});

Log.e(TAG, “———onCreate(): TaskId: ” + getTaskId() +”, hashCode: ” + hashCode());
}

@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
Log.e(TAG, “———onNewIntent(): TaskId: ” + getTaskId() +”, hashCode: ” + hashCode());
}

public static void open(Context context) {
context.startActivity(new Intent(context, SingleTopActivity.class));
}

}

OtherActivity:

public class OtherActivity extends AppCompatActivity {

private static final String TAG = OtherActivity.class.getSimpleName();

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_other);

findViewById(R.id.btn_singleTop).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
SingleTopActivity.open(OtherActivity.this);
}
});

Log.e(TAG, “———onCreate(): TaskId: ” + getTaskId() +”, hashCode: ” + hashCode());
}

public static void open(Context context) {
context.startActivity(new Intent(context, OtherActivity.class));
}

}

控制臺打印log以下:

首先,由于它們的taskId值都相同,因此它們同屬于一個任務棧。其次,第一次啟動SingleTopActivity的時候會執(zhí)行onCreate()方法新建一個實例,而后再次啟動SingleTopActivity頁面會回調onNewIntent(),說明沒有建立新的實例,并且hashCode值沒有發(fā)生改變。此時咱們繼續(xù)打開另外一個Activity,這時OtherActivity處于棧頂,咱們繼續(xù)啟動SingleTopActivity,這時發(fā)現(xiàn)又是執(zhí)行了onCreate(),說明又從新建立了新的實例,當咱們繼續(xù)啟動SingleTopActivity,發(fā)現(xiàn)回調了onNewIntent(),一樣hashCode值沒有發(fā)生改變,證實沒有從新建立實例。

分析總結:
經過上述案例概括為如下三點:

一、當前棧中已有該Activity的實例而且該實例位于棧頂時,不會建立實例,而是復用棧頂?shù)膶嵗?,而且會將Intent對象傳入,回調onNewInten()方法;
二、當前棧中已有該Activity的實例可是該實例不在棧頂時,其行為和standard啟動模式同樣,依然會建立一個新的實例;
三、當前棧中不存在該Activity的實例時,其行為同standard啟動模式。

使用場景:
這種模式應用場景的話,假如一個新聞客戶端,在通知欄收到了3條推送,點擊每一條推送會打開新聞的詳情頁,若是為默認的啟動模式的話,點擊一次打開一個頁面,會打開三個詳情頁,這確定是不合理的。若是啟動模式設置為singleTop,當點擊第一條推送后,新聞詳情頁已經處于棧頂,當咱們第二條和第三條推送的時候,只須要經過Intent傳入相應的內容便可,并不會從新打開新的頁面,這樣就能夠避免重復打開頁面了。

三、singleTask:站內復用模式
在這個模式下,若是棧中存在這個Activity的實例就會復用這個Activity,無論它是否位于棧頂,復用時,會將它上面的Activity所有出棧,由于singleTask自己自帶clearTop這種功能。而且會回調該實例的onNewIntent()方法。其實這個過程還存在一個任務棧的匹配,由于這個模式啟動時,會在本身須要的任務棧中尋找實例,這個任務棧就是經過taskAffinity屬性指定。若是這個任務棧不存在,則會建立這個任務棧。不設置taskAffinity屬性的話,默認為應用的包名。

使用案例:
MainActivity仍然是一個按鈕,點擊按鈕打開SingleTaskActivity,SingleTaskActivity有兩個按鈕,一個是打開SingleTaskActivity,另外一個一樣是打開OtherActivity,OtherActivity有一個按鈕,點擊按鈕能夠打開SingleTaskActivity。一樣咱們在onCreate()、onNewIntent()打印taskId和hashCode值。

打開步驟:MainActivity->SingleTaskActivity->SingleTaskActivity->OtherActivity->SingleTaskActivity->SingleTaskActivity

代碼和SingleTop基本同樣,只有Manifest中配置不一樣,這里再也不贅述。

一、不設置taskAffinity屬性,也就是默在同一個任務棧中。

Manifest中配置:

<activity
android:name=”.SingleTaskActivity”
android:launchMode=”singleTask”>
</activity>
1
2
3
4
控制臺打印log以下:

首先,由于發(fā)現(xiàn)它們的taskId值都相同,因此它們同屬于一個任務棧。其次,第一次啟動SingleTaskActivity的時候會執(zhí)行onCreate()方法新建一個實例,而后再次啟動SingleTaskActivity頁面會回調onNewIntent(),說明沒有建立新的實例,并且hashCode值沒有發(fā)生改變。此時咱們繼續(xù)打開另外一個Activity,而后繼續(xù)啟動SingleTaskActivity,這時發(fā)現(xiàn)仍然只回調onNewIntent(),說明沒有建立新的實例,當咱們繼續(xù)啟動SingleTaskActivity,仍然只是回調了onNewIntent(),此過程當中發(fā)現(xiàn)hashCode值始終沒有發(fā)生改變,證實引用都是同一個的實例。

二、設置taskAffinity屬性,singleTask所在的Activity與啟動它的Activity處于不一樣的任務棧中。

<activity
android:name=”.SingleTaskActivity”
android:launchMode=”singleTask”
android:taskAffinity=”${applicationId}.singleTask”>
</activity>

指定了taskAffinity后,咱們發(fā)現(xiàn)除了taskId有區(qū)別外,其余調用基本沒有什么區(qū)別。由于MainActivity沒有指定taskAffinity屬性,默認為包名,與SingleTaskActivity不一樣,因此在啟動SingleTaskActivity時,發(fā)現(xiàn)這個棧不存在,系統(tǒng)首先會建立這個棧而后將SingleTaskActivity壓入棧中。以后咱們發(fā)現(xiàn)只要棧中存在SingleTaskActivity這個實例,就會直接引用。

三、經過adb shell dumpsys activity activities查看當前運行的Activity

執(zhí)行完上面的步驟,咱們經過上面的信息得出,發(fā)現(xiàn)只有MainActivity和SingleTaskActivity在運行,并且也能夠看出確實有1909和1910兩個任務棧。那OtherActivity哪去了?那是由于SingleTaskActivity具備ClearTop的功能,當復用SingleTashActivity的時候會將棧中SingleTaskActivity之上的Activity所有清掉,因此OtherActivity實際上是被銷毀了。

分析總結:
在復用的時候,首先會根據(jù)taskAffinity去找對應的任務棧:
一、若是不存在指定的任務棧,系統(tǒng)會新建對應的任務棧,并新建Activity實例壓入棧中。
二、若是存在指定的任務棧,則會查找該任務棧中是否存在該Activity實例
a、若是不存在該實例,則會在該任務棧中新建Activity實例。
b、若是存在該實例,則會直接引用,而且回調該實例的onNewIntent()方法。而且任務棧中該實例之上的Activity會被所有銷毀。

使用場景:
SingleTask這種啟動模式最常使用的就是一個APP的首頁,由于通常為一個APP的第一個頁面,且長時間保留在棧中,因此最適合設置singleTask啟動模式來復用。

四、singleInstance:單實例模式
單實例模式,顧名思義,只有一個實例。該模式具有singleTask模式的全部特性外,與它的區(qū)別就是,這種模式下的Activity會單獨占用一個Task棧,具備全局惟一性,即整個系統(tǒng)中就這么一個實例,因為棧內復用的特性,后續(xù)的請求均不會建立新的Activity實例,除非這個特殊的任務棧被銷毀了。以singleInstance模式啟動的Activity在整個系統(tǒng)中是單例的,若是在啟動這樣的Activiyt時,已經存在了一個實例,那么會把它所在的任務調度到前臺,重用這個實例。

Manifest中配置:
<activity
android:name=”.SingleInstanceActivity”
android:launchMode=”singleInstance”>
</activity>

使用案例:
使用上面一樣的代碼進行測試:

經過測試發(fā)現(xiàn),在第一次打開SingleInstanceActivity的時候,因為系統(tǒng)不存在該實例,因此系統(tǒng)會新建一個任務棧來存放該Activity實例,并且只要打開過一次該Activity,后面不管何時再次啟動該Activity,都會直接引用第一次建立的實例,并且會回調該實例的onNewIntent()方法。

分析總結:
啟動該模式Activity的時候,會查找系統(tǒng)中是否存在:
一、不存在,首先會新建一個任務棧,其次建立該Activity實例。
二、存在,則會直接引用該實例,而且回調onNewIntent()方法。
特殊狀況:該任務?;蛟搶嵗讳N毀,系統(tǒng)會從新建立。

使用場景:
很常見的是,電話撥號盤頁面,經過本身的應用或者其余應用打開撥打電話頁面 ,只要系統(tǒng)的棧中存在該實例,那么就會直接調用。

3、總結在使用APP過程當中,不可避免頁面之間的跳轉,那么就會涉及到啟動模式。其實在對界面進行跳轉時,Android系統(tǒng)既能在同一個任務中對Activity進行調度,也能以Task(任務棧)為單位進行總體調度。在啟動模式為standard或singleTop時,通常是在同一個任務中對Activity進行調度,而在啟動模式為singleTask或singleInstance是,通常會對Task進行總體調度。


Android開發(fā)學習教程(24)- Android中Activity的啟動模式(LaunchMode)和使用場景的評論 (共 條)

分享到微博請遵守國家法律
武定县| 金川县| 通许县| 松原市| 邵东县| 柳林县| 古交市| 横山县| 龙门县| 隆德县| 吴旗县| 桃源县| 富锦市| 林甸县| 乃东县| 鹤山市| 秦安县| 清水县| 漳州市| 新宁县| 囊谦县| 年辖:市辖区| 始兴县| 大石桥市| 天津市| 东源县| 姜堰市| 五大连池市| 丰都县| 丹江口市| 遂平县| 平远县| 柏乡县| 扬州市| 南宫市| 阜宁县| 陆河县| 库车县| 通河县| 禹州市| 沾化县|