編輯:關於Android編程
Task是一個存在於Framework層的概念,容易與它混淆的有Application(應用)和Process(進程)。
application翻譯成中文時一般稱為“應用”或“應用程序”,在android中,總體來說一個應用就是一組組件的集合。眾所周知,android是在應用層組件化程度非常高的系統,android開發的第一課就是學習android的四大組件。當我們寫完了多個組件,並且在manifest文件中注冊了這些組件之後,把這些組件和組件使用到的資源打包成apk,我們就可以說完成了一個application。application和組件的關系可以在manifest文件中清晰地體現出來。
task是在程序運行時,只針對activity的概念。說白了,task是一組相互關聯的activity的集合,它是存在於framework層的一個概念,控制界面的跳轉和返回。這個task存在於一個稱為back stack的數據結構中,也就是說,framework是以棧的形式管理用戶開啟的activity。這個棧的基本行為是,當用戶在多個activity之間跳轉時,執行壓棧操作,當用戶按返回鍵時,執行出棧操作。
task是可以跨應用的,這正是task存在的一個重要原因。有的Activity,雖然不在同一個app中,但為了保持用戶操作的連貫性,把他們放在同一個任務中。例如,在我們的應用中的一個Activity A中點擊發送郵件,會啟動郵件程序的一個Activity B來發送郵件,這兩個activity是存在於不同app中的,但是被系統放在一個任務中,這樣當發送完郵件後,用戶按back鍵返回,可以返回到原來的Activity A中,這樣就確保了用戶體驗。
process一般翻譯成進程,進程是操作系統內核中的一個概念,表示直接受內核調度的執行單位。在應用程序的角度看,我們用java編寫的應用程序,運行在dalvik虛擬機中,可以認為一個運行中的dalvik虛擬機實例占有一個進程,所以,在默認情況下,一個應用程序的所有組件運行在同一個進程中。但是這種情況也有例外,即,應用程序中的不同組件可以運行在不同的進程中。只需要在manifest中用process屬性指定組件所運行的進程的名字
Android Activity 四種啟動模式 lunchMode 在Manifest 配置文件中的屬性如下:
(1) android:launchMode=”standard”(默認)
(2)android:launchMode=”singleTop”
(3)android:launchMode=”singleTask”
(4)android:launchMode=”singleInstance”
Activity的默認加載方法,即使某個Activity在 Task棧中已經存在,另一個activity通過Intent跳轉到該activity,同樣會新創建一個實例壓入棧中。例如:現在棧的情況為:A B C D,在D這個Activity中通過Intent跳轉到D,那麼現在的棧情況為: A B C D D 。此時如果棧頂的D通過Intent跳轉到B,則棧情況為:A B C D D B。此時如果依次按返回鍵,D D C B A將會依次彈出棧而顯示在界面上。
(1) 如果某個Activity的Launch mode設置成singleTop,那麼當該Activity位於棧頂的時候,再通過Intent跳轉到本身這個Activity,則將不會創建一個新的實例壓入棧中。例如:現在棧的情況為:A B C D。D的Launch mode設置成了singleTop,那麼在D中啟動Intent跳轉到D,那麼將不會新創建一個D的實例壓入棧中,此時棧的情況依然為:A B C D。但是如果此時B的模式也是singleTop,D跳轉到B,那麼則會新建一個B的實例壓入棧中,因為此時B不是位於棧頂,此時棧的情況就變成了:A B C D B。
(2)一個singleTop Activity 的實例可以無限多,唯一的區別是如果在棧頂已經有一個相同類型的Activity實例,Intent不會再創建一個Activity,而是通過onNewIntent()被發送到現有的Activity。
在singleTop模式下我們需要同時在onCreate() 和 onNewIntent()中處理發來的intent,以滿足不同情況。(3)使用場合:這種啟動模式的用例之一就是搜索功能。假設我們創建了一個搜索框,點擊搜索的時候將導航到一個顯示搜索結果列表的SearchActivity中,為了更好的用戶體驗,這個搜索框一般也會被放到SearchActivity中,這樣用戶想要再次搜索就不需要按返回鍵。
(4)而當Intent來自於另外一個應用的時候,新的Activity的啟動方式和standard模式是一致的(Lollipop以及之後:會創建一個新的任務)。
如果某個Activity是singleTask模式,那麼Task棧中將會只有一個該Activity的實例。例如:現在棧的情況為:A B C D。B的Launch mode為singleTask,此時D通過Intent跳轉到B,則棧的情況變成了:A B。而C和D被彈出銷毀了,也就是說位於B之上的實例都被銷毀了。
singleTask模式的Activity只允許在系統中有一個實例。如果系統中已經有了一個實例,持有這個實例的任務將移動到頂部,同時intent將被通過onNewIntent()發送。如果沒有,則會創建一個新的Activity並置放在合適的任務中。
一旦intent是從另外的應用發送過來,並且系統中也沒有任何Activity的實例,則會創建一個新的任務,並且新的Activity被作為根Activity創建。假設已經有了一個Activity的實例,不管它是在哪個任務中(包括上面的那種情況,在用於這個Activity的應用中),整個任務將被移到頂端,而singleTask Activity上面的所有 Activity 都將被銷毀, 用戶需要按back鍵遍歷玩棧中的Activity才能回到調用者任務。
應用場景:郵件客戶端的收件箱或者社交網絡的時間軸。這些Activity一般不會設計成擁有多個實例,singleTask可以滿足。但是在使用這種模式的時候必須要明智,因為有些Activity會在用戶不知情的情況下被銷毀。
**1. 設置了”singleTask”啟動模式的Activity,它在啟動的時候,會先在系統中查找屬性值affinity等於它的屬性值taskAffinity的任務存在;如果存在這樣的任務,它就會在這個任務中啟動,否則就會在新任務中啟動。因此,如果我們想要設置了”singleTask”啟動模式的Activity在新的任務中啟動,就要為它設置一個獨立的taskAffinity屬性值。
2. 如果設置了”singleTask”啟動模式的Activity不是在新的任務中啟動時,它會在已有的任務中查看是否已經存在相應的Activity實例,如果存在,就會把位於這個Activity實例上面的Activity全部結束掉,即最終這個Activity實例會位於任務的堆棧頂端中。**
將Activity壓入一個新建的任務棧中。例如:Task棧1的情況為:A B C。C通過Intent跳轉到D,而D的Launch mode為singleInstance,則將會新建一個Task棧2。此時Task棧1的情況還是為:A B C。Task棧2的情況為:D。此時屏幕界面顯示D的內容,如果這時D又通過Intent跳轉到D,則Task棧2中也不會新建一個D的實例,所以兩個棧的情況也不會變化。而如果D跳轉到C,則棧1的情況變成了:A B C C,因為C的Launch mode為standard,此時如果再按返回鍵,則棧1變成:A B C。也就是說現在界面還顯示C的內容,不是D。
這個模式非常接近於singleTask,系統中只允許一個Activity的實例存在。區別在於持有這個Activity的任務中只能有一個Activity:即這個單例本身。
不過結果卻很怪異,從dumpsys提供的信息來看,似乎系統中有兩個任務但任務管理器中只顯示一個,即最後被移到頂部的那個。導致雖然後台有一個任務在運行,我們卻無法切換回去,這一點也不科學。
因為這個任務只有一個Activity,我們再也無法切回到任務#1了。唯一的辦法是重新在launcher中啟動這個應用。
不過這個問題也有解決方案,就像我們在singleTask Acvity中做的,只要為singleInstance Activity設置taskAffinity屬性就可以了。使用場景:撥打電話界面
這種模式很少被使用。實際使用的案例如Launcher的Activity或者100%確定只有一個Activity的應用。總之除非完全有必要,不然我不建議使用這種模式。
個人想法:在不指定android:taskAffinity的情況下,SingleTask存在的task是和應用一致的,而SingleInstance是單獨存在一個新的task中,並且不能夠通過返回到底這個界面,只能重新加載。如果其他應用B調用了應用A中的singleTask界面b,如果開始之前,a->b->c,B調用b之後,A棧中變成a->b,c被銷毀,此時點擊後退鍵,先回到a,知道A應用退出後回到應用B的調用頁面。
有這樣的需求,多個Task共享一個Activity(singleTask是在一個task中共享一個Activity)。
現成的例子是google地圖。比如我有一個應用是導游方面的,其中調用的google地圖Activity。那麼現在我比如按home鍵,然後到應用列表中打開google地圖,你會發現顯示的就是剛才的地圖,實際上是同一個Activity。如果使用前三種模式,是無法實現這個需求的。google地圖應用中有多個上下文Activity,比如路線查詢等的,導游應用也有一些上下文Activity。在各自應用中回退要回退到各自的上下文Activity中。
singleInstance模式解決了這個問題(繞了這麼半天才說到正題)。讓這個模式下的Activity單獨在一個task棧中。這個棧只有一個Activity。導游應用和google地圖應用發送的intent都由這個Activity接收和展示。
這裡又有兩個問題:
如果是這種情況,多個task棧也可以看作一個應用。比如導游應用啟動地圖Activity,實際上是在導游應用task棧之上singleInstance模式創建的(如果還沒有的話,如果有就是直接顯示它)一個新棧,當這個棧裡面的唯一Activity,地圖Activity回退的時候,只是把這個棧移開了,這樣就看到導游應用剛才的Activity了;
多個應用(Task)共享一個Activity要求這些應用都沒有退出,比如剛才強調要用home鍵從導游應用切換到地圖應用。因為,如果退出導游應用,而這時也地圖應用並未運行的話,那個單獨的地圖Activity(task)也會退出了。
被啟動activity加載模式singleTask,獲取不到返回值,0既是RESULT_CANCELED,也就是說直接取消了,onActivityResult收到RESULT_CANCELED
singleInstance,他和singleTask類似,不同點是singleInstance要求activity的實例不僅只有一個,並且整個task中只有一個activity實例,而singleTask所在的棧中允許存在其他activity的實例。
由此我們可以知道設置了singleInstance的activity也具有上面的特性,此外,啟動的activity設置了singleInstance,那麼無論被啟動的activity有沒有設置singleInstance,都無法獲取返回值
啟動 Activity 時,您可以通過在傳遞給 startActivity() 的 Intent 中加入相應的標志,修改 Activity 與其任務的默認關聯方式。可用於修改默認行為的標志包括:
在新任務中啟動 Activity。如果已為正在啟動的 Activity 運行任務,則該任務會轉到前台並恢復其最後狀態,同時 Activity 會在 onNewIntent() 中收到新 Intent。
正如前文所述,這會產生與 “singleTask” launchMode 值相同的行為。
如果正在啟動的 Activity 是當前 Activity(位於返回棧的頂部),則 現有實例會接收對 onNewIntent() 的調用,而不是創建 Activity 的新實例。
正如前文所述,這會產生與 “singleTop” launchMode 值相同的行為。
如果正在啟動的 Activity 已在當前任務中運行,則會銷毀當前任務頂部的所有 Activity,並通過 onNewIntent() 將此 Intent 傳遞給 Activity 已恢復的實例(現在位於頂部),而不是啟動該 Activity 的新實例。
產生這種行為的 launchMode 屬性沒有值。FLAG_ACTIVITY_CLEAR_TOP 通常與 FLAG_ACTIVITY_NEW_TASK 結合使用。一起使用時,通過這些標志,可以找到其他任務中的現有 Activity,並將其放入可從中響應 Intent 的位置。
當設置了
android:launchMode=”singleTask”
時,系統會查找 對應的taskAffinity任務空間是否有啟動過這個activity ,如果沒有啟動,則在這個taskAffinity 任務空間啟動,如果有啟動過,則將這個activity 推送到棧頂, 那麼在這個activity 之上的activity 都被推送出棧了,不在任務Task 中,也就是 Ondestroy 了。
Intent的常用Flag參數:
例如現在的棧情況為:A B C D 。D此時通過intent跳轉到B,如果這個intent添加FLAG_ACTIVITY_CLEAR_TOP 標記,則棧情況變為:A B。如果沒有添加這個標記,則棧情況將會變成:A B C D B。也就是說,如果添加了FLAG_ACTIVITY_CLEAR_TOP 標記,並且目標Activity在棧中已經存在,則將會把位於該目標activity之上的activity從棧中彈出銷毀。這跟上面把B的Launch mode設置成singleTask類似。
例如現在棧1的情況是:A B C。C通過intent跳轉到D,並且這個intent添加了FLAG_ACTIVITY_NEW_TASK 標記,如果D這個Activity在Manifest.xml中的聲明中添加了Task affinity,並且和棧1的affinity不同,系統首先會查找有沒有和D的Task affinity相同的task棧存在,如果有存在,將D壓入那個棧,如果不存在則會新建一個D的affinity的棧將其壓入。如果D的Task affinity默認沒有設置,或者和棧1的affinity相同,則會把其壓入棧1,變成:A B C D,這樣就和不加FLAG_ACTIVITY_NEW_TASK 標記效果是一樣的了。 注意如果試圖從非activity的非正常途徑啟動一個activity,比如從一個service中啟動一個activity,則intent比如要添加FLAG_ACTIVITY_NEW_TASK 標記。
例如現在棧情況為:A B C。C通過intent跳轉到D,這個intent添加FLAG_ACTIVITY_NO_HISTORY標志,則此時界面顯示D的內容,但是它並不會壓入棧中。如果按返回鍵,返回到C,棧的情況還是:A B C。如果此時D中又跳轉到E,棧的情況變為:A B C E,此時按返回鍵會回到C,因為D根本就沒有被壓入棧中。
和上面Activity的 Launch mode的singleTop類似。如果某個intent添加了這個標志,並且這個intent的目標activity就是棧頂的activity,那麼將不會新建一個實例壓入棧中。
allowTaskReparenting:設置成true時,和Intent的FLAG_ACTIVITY_NEW_TASK 標記類似。
alwaysRetainTaskStat: 如果用戶長時間將某個task 移入後台,則系統會將該task的棧內容彈出只剩下棧底的activity,此時用戶再返回,則只能看到根activity了。如果棧底的 activity的這個屬性設置成true,則將阻止這一行為,從而保留所有的棧內容。
clearTaskOnLaunch:根activity的這個屬性設置成true時,和上面的alwaysRetainTaskStat 的屬性為true情況搞好相反。
finishOnTaskLaunch:對於任何activity,如果它的這個屬性設置成true,則當task被放置到後台,然後重新啟動後,該activity將不存在了。
“關聯”指示 Activity 優先屬於哪個任務。默認情況下,同一應用中的所有 Activity 彼此關聯。 因此,默認情況下,同一應用中的所有 Activity 優先位於相同任務中。 不過,您可以修改 Activity 的默認關聯。 在不同應用中定義的 Activity 可以共享關聯,或者可為在同一應用中定義的 Activity 分配不同的任務關聯。
可以使用 元素的 taskAffinity 屬性修改任何給定 Activity 的關聯。taskAffinity 屬性取字符串值,該值必須不同於 在 元素中聲明的默認軟件包名稱,因為系統使用該名稱標識應用的默認任務關聯。
默認情況下,新 Activity 會啟動到調用 startActivity() 的 Activity 任務中。它將推入與調用方相同的返回棧。 但是,如果傳遞給 startActivity() 的 Intent 包含 FLAG_ACTIVITY_NEW_TASK 標志,則系統會尋找其他任務來儲存新 Activity。這通常是新任務,但未做強制要求。 如果現有任務與新 Activity 具有相同關聯,則會將 Activity 啟動到該任務中。 否則,將開始新任務。
如果此標志導致 Activity 開始新任務,且用戶按“主頁”按鈕離開,則必須為用戶提供導航回任務的方式。 有些實體(如通知管理器)始終在外部任務中啟動 Activity,而從不作為其自身的一部分啟動 Activity,因此它們始終將 FLAG_ACTIVITY_NEW_TASK 放入傳遞給 startActivity() 的 Intent 中。請注意,如果 Activity 能夠由可以使用此標志的外部實體調用,則用戶可以通過獨立方式返回到啟動的任務,例如,使用啟動器圖標(任務的根 Activity 具有 CATEGORY_LAUNCHER Intent 過濾器;請參閱下面的啟動任務部分)。
在這種情況下,Activity 可以從其啟動的任務移動到與其具有關聯的任務(如果該任務出現在前台)。
例如,假設將報告所選城市天氣狀況的 Activity 定義為旅行應用的一部分。 它與同一應用中的其他 Activity 具有相同的關聯(默認應用關聯),並允許利用此屬性重定父級。當您的一個 Activity 啟動天氣預報 Activity 時,它最初所屬的任務與您的 Activity 相同。 但是,當旅行應用的任務出現在前台時,系統會將天氣預報 Activity 重新分配給該任務並顯示在其中。
android 按home鍵返回到桌面後,再按桌面應用圖標又重新打開該應用的解決方法。
解決方法:這個問題是因為在AndroidManifest.xml中,你的啟動activity中加了android:launchMode=”singleTask”,將這行代碼去掉就可以了。
拍照——裁剪,或者是選擇圖片——裁剪,是我們設置頭像或上傳圖片時經常需要的一組操作。上篇講了Camera的使用,這篇講一下
前言:項目中除了登陸,支付等接口采用rsa非對稱加密,之外的采用aes對稱加密,今天我們來認識一下aes加密。 其他幾種加密方式: •An
概述:此部分內容涉及到android的自定義View、自定義屬性和Android圖形圖像處理的綜合應用:Bitmap、Path、Matrix、Canvas。圖片打碼以及如
android矢量動畫!直接來個例子就明白了!(這裡我把與動畫無關的屬性都用…表示)首先你要有個矢量圖比如這個矢量圖xml文件叫”vector1