日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

android 怎么自定义任务栈,Android中的Activity详解--启动模式与任务栈

發布時間:2023/12/10 Android 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android 怎么自定义任务栈,Android中的Activity详解--启动模式与任务栈 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

Activity

生命周期

任務棧

啟動模式

Intent Flag

taskAffinity屬性

1.Activity

activity的簡單介紹就不寫了,作為最常用的四大組件之一,肯定都很熟悉其基本用法了。

2.生命周期

首先,是都很熟悉的一張圖,即官方介紹的Activity生命周期圖.

Activity生命周期圖

情景:打開某個應用的的FirstActivity調用方法如下:

由于之前已經很熟悉了,這里就簡單貼一些圖。

Paste_Image.png

按下返回鍵:

Paste_Image.png

重新打開并按下home鍵:

Paste_Image.png

再重新打開:

Paste_Image.png

在其中打開一個DialogActivity(SecondActivity)

Paste_Image.png

按下返回:

Paste_Image.png

修改SecondAcitvity為普通Activity,依舊是上述操作:

Paste_Image.png

這里強調一下onSaveInstanceState(Bundle outState)方法的調用時機:

當Activity有可能被系統殺掉時調用,注意,一定是被系統殺掉,自己調用finish是不行的。

測試如下:FirstActivity啟動SecondActivity:

Paste_Image.png

如果SecondActivity是android:theme="@android:style/Theme.Dialog"那么:

Paste_Image.png

如果FirstActivity啟動SecondActivity后自己調用了finish方法:

Paste_Image.png

也就是說,只要一個Activity轉為后臺,那么就會調用此方法,因為其有可能被系統殺掉,其中存的Bundle對象就是用來存儲數據的,這個也就是onCreate方法中Bundle對象參數savedInstanceState的由來。

3.Acitvity任務棧

一個App會包含很多個Activity,多個Activity之間通過intent進行跳轉,那么原始的Activity就是使用棧這個數據結構來保存的。

Task

A task is a collection of activities that users interact with when performing a certain job. The activities are arranged in a stack (theback stack), in the order in which each activity is opened.

即若干個Activity的集合的棧表示一個Task。

當App啟動時如果不存在當前App的任務棧就會自動創建一個,默認情況下一個App中的所有Activity都是放在一個Task中的,但是如果指定了特殊的啟動模式,那么就會出現同一個App的Activity出現在不同的任務棧中的情況,即會有任務棧中包含來自于不同App的Activity。

4.啟動模式

standard

標準模式,在不指定啟動模式的情況下都是以此種方式啟動的。每次啟動都會創建一個新的Activity實例,覆蓋在原有的Activity上,原有的Activity入棧。

測試如下:在FirstActivity中啟動FirstActivity:

Paste_Image.png

當只有一個FirstActivity時堆棧情況:

Paste_Image.png

當在FirstActivity中啟動FirstActivity時堆棧情況:

Paste_Image.png

這就很顯然了,任務棧中一共有兩個FirstActivity,即表示每次啟動FirstActivity都是創建了一個新的實例。

singleTop

此種模式下,Activity在啟動時會進行判斷,如果當前的App的棧頂的Activity即正在活動的Activity就是將要啟動的Activity,那么就不會創建新的實例,直接使用棧頂的實例。

測試,設置FirstActivity為此啟動模式,多次點擊FirstActivity中的啟動FirstActivity的按鈕查看堆棧情況:

(其實點擊按鈕沒有啟動新Activity的動畫就可以看出并沒有啟動新Activity)

Paste_Image.png

果然,堆棧中只有一個FirstActivity

如果我在FirstActivity中啟動了SecondActivity,此時FirstActivity不就不在棧頂了么,此時我再啟動FirstActivity會怎樣呢?

測試如下:

Paste_Image.png

很好的驗證了,只有在棧頂時,才不會創建新實例。

這種啟動模式很適用于接收到消息之后進行顯示的界面,總不能每次來消息都創建新實例,那一次來個十幾條消息豈不是爆炸了。

在此種模式下,在不創建新的實例的時候,會調用onNewIntent()方法。

總結:棧頂的Activity只會有一個實例,在棧頂的情況下重復啟動該Activity只會復用該Activity,而不會創建一個新的,除了棧頂的Activity外,其他的和standard類似,每次啟動都會被創建一個新的實例。

onNewIntent(Intent intent)方法介紹

官方解釋如下:

This is called for activities that set launchMode to "singleTop" in

* their package, or if a client used the {@link Intent#FLAG_ACTIVITY_SINGLE_TOP}

* flag when calling {@link #startActivity}. In either case, when the

* activity is re-launched while at the top of the activity stack instead

* of a new instance of the activity being started, onNewIntent() will be

* called on the existing instance with the Intent that was used to

* re-launch it.

*

*

An activity will always be paused before receiving a new intent, so

* you can count on {@link #onResume} being called after this method.

*

*

Note that {@link #getIntent} still returns the original Intent. You

* can use {@link #setIntent} to update it to this new Intent.

*

* @param intent The new intent that was started for the activity.

大意就是:

對于使用singleTop啟動或Intent.FLAG_ACTIVITY_SINGLE_TOP啟動的Activity,當該Activity被重復啟動(注意一定是re-launched,第一次啟動時不會調用)時就會調用此方法。

且調用此方法之前會先暫停Activity也就是先調用onPause方法。

而且,即使是在新的調用產生后此方法被調用,但是通過getIntent方法獲取到的依舊是以前的Intent,可以通過setIntent方法設置新的Intent。

方法參數就是新傳遞的Intent.

singleTask

1.如果是同一個App中啟動某個設置了此模式的Activity的話,如果棧中已經存在該Activity的實例,那么就會將該Activity上面的Activity清空,并將此實例放在棧頂。

測試:SecondActivity啟動模式設為singleTask,啟動三個Activity:

Paste_Image.png

然后在ThirdActivity中啟動SecondActivity(注意不是返回,而是啟動):

Paste_Image.png

果然,SecondActivity上的ThirdActivity被清掉了

2.如果是其他應用的Activity啟動的本應用中此Activity,那么

- 本應用未啟動時,在另一個應用的ActivityY中啟動SecondActivity:

Paste_Image.png

顯然,此時這個SecondActivity是在一個單獨的任務棧中的,且是處于前臺的,按下返回鍵,SecondActivity結束,返回到ActivityY。

- 本應用已經啟動了,在后臺運行,任務棧中是FirstActivity和SecondActivity,在另一個應用的ActivityY中啟動此Activity,此時任務棧的狀態:

Paste_Image.png

兩個任務棧,每個棧中都有兩個Activity。

注意,此時如果按下返回鍵,會出現什么情況呢,到底是返回到ActivityY,還是返回到FirstActivity?

結果如下:

Paste_Image.png

前臺Activity竟然變成了FirstActivity!繼續按下返回鍵,就會返回到ActivityY,ActivityX,然后退出。

也就是說,在ActivityY啟動了SecondActivity時,連帶著SecondActivity的任務棧也被帶到了前臺。

那么我不禁要問了,如果SecondActivity啟動模式是默認的,會不會是此種情況呢?,其實按照我們前面學的,按照分析的話,應該是SecondActivity在ActivityY所在的App所對應的任務棧中創建一個新的實例,跟原本的SecondActivity所在后臺任務棧沒有一毛錢關系。

- 本應用已經啟動了三個Activity,任務棧中是FirstActivity和SecondActivity和ThirdActivity,此時再由ActivityY啟動:

那么稍微思考一下就可以肯定運行結果跟上面是完全相同的,因為在跳轉到SecondActivity時,其上面的Activity已經被清空了。

singleInstance

這個模式就很好記,以此模式啟動的Activity會存放在一個單獨的任務棧中,且只會有一個實例。

測試:SecondActivity啟動模式設為singleInstance

FirstActivity->SesondActivity->ThirdActivity->SecondActivity->ThirdActivity

結果:

Paste_Image.png

顯然,啟動了兩次ThirdActivity任務棧中就有兩個實例,而SecondActivity在另外一個任務棧中,且只有一個。

5.Intent Flag設置啟動模式

在使用Intent啟動一個Activity時可以設置啟動該Activity的啟動模式:

這個屬性有很多,大致列出幾個:

Intent.FLAG_ACTIVITY_NEW_TASK

每個啟動的Activity都在一個新的任務棧中

Intent.FLAG_ACTIVITY_SINGLE_TOP

singleTop

Intent.FLAG_ACTIVITY_CLEAR_TOP

singleTask

Intent.FLAG_ACTIVITY_NO_HISTORY

用此種方式啟動的Activity,在它啟動了其他Activity后,會自動finish.

6.taskAffinity屬性

官方文檔介紹如下:

The task that the activity has an affinity for. Activities with the same affinity conceptually belong to the same task (to the same "application" from the user's perspective). The affinity of a task is determined by the affinity of its root activity.The affinity determines two things — the task that the activity is re-parented to and the task that will house the activity when it is launched with the FLAG_ACTIVITY_NEW_TASK flag.

By default, all activities in an application have the same affinity. You can set this attribute to group them differently, and even place activities defined in different applications within the same task. To specify that the activity does not have an affinity for any task, set it to an empty string.

If this attribute is not set, the activity inherits the affinity set for the application (see theelement's taskAffinity.

The name of the default affinity for an application is the package name set by theelement.

大意如下:

這個屬性表示的是一個Activity對任務棧的親和度。有相同的affinity的Activity屬于同一個Task,即affinity相同的Activity會被加入同一任務棧。一個任務棧的affinity由其affinity值確定或是其根Activity的affinity確定。這個屬性決定兩件事,①Activity被re-parented時的任務棧,②以FLAG_ACTIVITY_NEW_TASK啟動的Activity所在的任務棧。

默認情況下,同一個應用內的所有的Activity都擁有相同的affinity,你可以通過設置這個值來給Activity分組,甚至將不同應用的Activity放在相同的任務棧中。為了表明一個Activity對任何一個任務棧都不具有親和力,那么將其設為空字符串。

如果這個值沒有設置,那么就默認使用application標簽下的這個值。

默認的affinity值為manifest標簽下設置的包名。

這樣看來的話,通俗易懂的講,就是給每一個任務棧起個名,給每個Activity也起個名,在Activity以singleTask模式啟動時,就檢查有沒有跟此Activity的名相同的任務棧,有的話就將其加入其中。沒有的話就按照這個Activity的名創建一個任務棧。

測試:在App1中設置SecondActivity的taskAffinity為“gsq.test”,App2中的ActivityX的taskAffinity也設為“gsq.test”

FirstActivity->SesondActivity->home->ActivityX

任務棧信息如下:

Paste_Image.png

結果很顯然了。

測試:在上述基礎上,在ActivityX中進行跳轉到ActivityY,ActivityY不指定啟動模式和taskAffinity。結果如下:

Paste_Image.png

發現ActivityY在gsq.test任務棧中,這是由于其啟動模式是Standard,也就是在啟動這個Activity的所在的任務任務棧中。

再將ActivityY指定啟動模式singleTask:

Paste_Image.png

這樣就沒問題了,ActivityY在一個新的任務棧中,名稱為包名。

這時從ActivityY跳轉到SecondActivity,那應該是gsq.test任務棧只有SecondActivity,ActivityX已經沒有了。因為其啟動模式是singleTask,在啟動它時發現已經有一個實例存在,就把它所在的任務棧上面的Activity都清空了并將其置于棧頂。

還有一點需要提一下,在上面,FirstActivity是App1的lunch Activity,但是由于SecondActivity并沒有指定MAIN和LAUNCHER過濾器,故在FirstActivity跳轉到SecondActivity時,按下home鍵,再點開App1,回到的是FirstActivity。

大致就先寫這么多吧,好像有點長,廢話有點多,估計也有錯別字,不要太在意~~~

總結

以上是生活随笔為你收集整理的android 怎么自定义任务栈,Android中的Activity详解--启动模式与任务栈的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。