<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                # 4.1.3 Activity登堂入室 ## 1.Activity,Window與View的關系 > 好吧,本來就想了解下他們幾個的關系,然后手多多,然后就開始看起他們的調用過程來了...結果扣了兩個小時,只理解了很小很小的一部分,果然,到底層擼源碼的都是大神,比如老羅,還沒到那個等級,下面是自己查閱資料,看了下一點源碼的歸納所得,如果哪寫錯了歡迎指出!下面貼下小結圖: ![](http://www.runoob.com/wp-content/uploads/2015/08/93497523.jpg) **流程解析:** Activity調用startActivity后最后會調用attach方法,然后在PolicyManager實現一個Ipolicy接口,接著實現一個Policy對象,接著調用makenewwindow(Context)方法,該方法會返回一個PhoneWindow對象,而PhoneWindow 是Window的子類,在這個PhoneWindow中有一個DecorView的內部類,是所有應用窗口的根View,即View的老大, 直接控制Activity是否顯示(引用老司機原話..),好吧,接著里面有一個LinearLayout,里面又有兩個FrameLayout他們分別拿來裝ActionBar和CustomView,而我們setContentView()加載的布局就放到這個CustomView中! **總結下這三者的關系:** 打個牽強的比喻: 我們可以把這三個類分別堪稱:畫家,畫布,畫筆畫出的東西; 畫家通過畫筆( **LayoutInflater.infalte**)畫出圖案,再繪制在畫布(**addView**)上! 最后顯示出來(**setContentView**) ## 2.Activity,Task和Back Stack的一些概念 接著我們來了解Android中Activity的管理機制,這就涉及到了兩個名詞:Task和Back Stack了! **概念解析:** 我們的APP一般都是由多個Activity構成的,而在Android中給我們提供了一個**Task(任務)**的概念, 就是將多個相關的Activity收集起來,然后進行Activity的跳轉與返回!當然,這個Task只是一個 frameworker層的概念,而在Android中實現了Task的數據結構就是**Back Stack(回退堆棧)**! 相信大家對于棧這種數據結構并不陌生,Java中也有個Stack的集合類!棧具有如下特點: > **先進先出(LIFO),常用操作入棧(push),出棧(pop),處于最頂部的叫棧頂,最底部叫棧底** 而Android中的Stack Stack也具有上述特點,他是這樣來管理Activity的: > 當切換到新的Activity,那么該Activity會被壓入棧中,成為棧頂! 而當用戶點擊Back鍵,棧頂的Activity出棧,緊隨其后的Activity來到棧頂! 我們來看下官方文檔給出的一個流程圖: ![](http://www.runoob.com/wp-content/uploads/2015/08/93537362.jpg) **流程解析:** 應用程序中存在A1,A2,A3三個activity,當用戶在Launcher或Home Screen點擊應用程序圖標時, 啟動主A1,接著A1開啟A2,A2開啟A3,這時棧中有三個Activity,并且這三個Activity默認在 同一個任務(Task)中,當用戶按返回時,彈出A3,棧中只剩A1和A2,再按返回鍵, 彈出A2,棧中只剩A1,再繼續按返回鍵,彈出A1,任務被移除,即程序退出! 接著在官方文檔中又看到了另外兩個圖,處于好奇,我又看了下解釋,然后跟群里的人討論了下: ![](http://www.runoob.com/wp-content/uploads/2015/08/76132682.jpg) ![](http://www.runoob.com/wp-content/uploads/2015/08/2159561.jpg) 然后還有這段解釋: ![](http://www.runoob.com/wp-content/uploads/2015/08/94874923.jpg) **然后總結下了結論:** > Task是Activity的集合,是一個概念,實際使用的Back Stack來存儲Activity,可以有多個Task,但是 同一時刻只有一個棧在最前面,其他的都在后臺!那棧是如何產生的呢? > > 答:當我們通過主屏幕,點擊圖標打開一個新的App,此時會創建一個新的Task!舉個例子: > 我們通過點擊通信錄APP的圖標打開APP,這個時候會新建一個棧1,然后開始把新產生的Activity添加進來,可能我們在通訊錄的APP中打開了短信APP的頁面,但是此時不會新建一個棧,而是繼續添加到棧1中,這是 Android推崇一種用戶體驗方式,即不同應用程序之間的切換能使用戶感覺就像是同一個應用程序, 很連貫的用戶體驗,官方稱其為seamless (無縫銜接)! ——————這個時候假如我們點擊Home鍵,回到主屏幕,此時棧1進入后臺,我們可能有下述兩種操作: > 1)點擊菜單鍵(正方形那個按鈕),點擊打開剛剛的程序,然后棧1又回到前臺了! 又或者我們點擊主屏幕上通信錄的圖標,打開APP,此時也不會創建新的棧,棧1回到前臺! > 2)如果此時我們點擊另一個圖標打開一個新的APP,那么此時則會創建一個新的棧2,棧2就會到前臺, 而棧1繼續呆在后臺; > 3) 后面也是這樣...以此類推! ## 3.Task的管理 ### 1)文檔翻譯: 好的,繼續走文檔,從文檔中的ManagingTasks開始,大概的翻譯如下: ### 1)文檔翻譯 繼續走文檔,從文檔中的ManagingTasks開始,翻譯如下: > 如上面所述,Android會將新成功啟動的Activity添加到同一個Task中并且按照以"先進先出"方式管理多個Task 和Back Stack,用戶就無需去擔心Activites如何與Task任務進行交互又或者它們是如何存在于Back Stack中! 或許,你想改變這種正常的管理方式。比如,你希望你的某個Activity能夠在一個新的Task中進行管理; 或者你只想對某個Activity進行實例化,又或者你想在用戶離開任務時清理Task中除了根Activity所有Activities。你可以做這些事或者更多,只需要通過修改AndroidManifest.xml中 &lt; activity &gt;的相關屬性值或者在代碼中通過傳遞特殊標識的Intent給startActivity( )就可以輕松的實現 對Actvitiy的管理了。 **&lt; activity &gt;中我們可以使用的屬性如下:** > * **taskAffinity** > * **launchMode** > * **allowTaskReparenting** > * **clearTaskOnLaunch** > * **alwaysRetainTaskState** > * **finishOnTaskLaunch** **你能用的主要的Intent標志有:** > * **FLAG_ACTIVITY_NEW_TASK** > * **FLAG_ACTIVITY_CLEAR_TOP** > * **FLAG_ACTIVITY_SINGLE_TOP** 好的,接下來逐個介紹這些怎么用: ### 2)taskAffinity和allowTaskReparenting 默認情況下,一個應用程序中的**所有activity都有一個Affinity**,這讓它們屬于同一個Task。 你可以理解為是否處于同一個Task的標志,然而,每個Activity可以通過 &lt; activity&gt;中的taskAffinity屬性設置單獨的Affinity。 不同應用程序中的Activity可以共享同一個Affinity,同一個應用程序中的不同Activity 也可以設置成不同的Affinity。 Affinity屬性在2種情況下起作用: > 1)當啟動 activity的Intent對象包含**FLAG_ACTIVITY_NEW_TASK**標記: 當傳遞給startActivity()的Intent對象包含 FLAG_ACTIVITY_NEW_TASK標記時,系統會為需要啟動的Activity尋找與當前Activity不同Task。如果要啟動的 Activity的Affinity屬性與當前所有的Task的Affinity屬性都不相同,系統會新建一個帶那個Affinity屬性的Task,并將要啟動的Activity壓到新建的Task棧中;否則將Activity壓入那個Affinity屬性相同的棧中。 > > 2)**allowTaskReparenting**屬性設置為true 如果一個activity的allowTaskReparenting屬性為true, 那么它可以從一個Task(Task1)移到另外一個有相同Affinity的Task(Task2)中(Task2帶到前臺時)。 如果一個.apk文件從用戶角度來看包含了多個"應用程序",你可能需要對那些 Activity賦不同的Affinity值。 ### 3)launchMode: 四個可選值,啟動模式我們研究的核心,下面再詳細講! 他們分別是:**standard**(默認),**singleTop**,**singleTask**,**singleInstance** ### 4)清空棧 > 當用戶長時間離開Task(當前task被轉移到后臺)時,系統會清除task中棧底Activity外的所有Activity 。這樣,當用戶返回到Task時,只留下那個task最初始的Activity了。我們可以通過修改下面這些屬性來 改變這種行為! > > **alwaysRetainTaskState**: 如果棧底Activity的這個屬性被設置為true,上述的情況就不會發生。 Task中的所有activity將被長時間保存。 > > **clearTaskOnLaunch** 如果棧底activity的這個屬性被設置為true,一旦用戶離開Task, 則 Task棧中的Activity將被清空到只剩下棧底activity。這種情況剛好與 alwaysRetainTaskState相反。即使用戶只是短暫地離開,task也會返回到初始狀態 (只剩下棧底acitivty)。 > > **finishOnTaskLaunch** 與clearTaskOnLaunch相似,但它只對單獨的activity操 作,而不是整個Task。它可以結束任何Activity,包括棧底的Activity。 當它設置為true時,當前的Activity只在當前會話期間作為Task的一部分存在, 當用戶退出Activity再返回時,它將不存在。 ## 4.Activity的四種加載模式詳解: 接下來我們來詳細地講解下四種加載模式: 他們分別是:**standard**(默認),**singleTop**,**singleTask**,**singleInstance** 在泡在網上的日子看到一篇圖文并茂的講解啟動模式的,很贊,可能更容易理解吧,這里借鑒下: 原文鏈接:[Activity啟動模式圖文詳解:standard, singleTop, singleTask 以及 singleInstance](http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0520/2897.html) 英文原文:[Understand Android Activity's launchMode: standard, singleTop, singleTask and singleInstance](http://inthecheesefactory.com/blog/understand-android-activity-launchmode/en) 另外還有一篇詳細講解加載模式的:[Android中Activity四種啟動模式和taskAffinity屬性詳解](http://blog.csdn.net/zhangjg_blog/article/details/10923643) **先來看看總結圖:** ![](http://www.runoob.com/wp-content/uploads/2015/08/50179298.jpg) **模式詳解:** ### standard模式: 標準啟動模式,也是activity的默認啟動模式。在這種模式下啟動的activity可以被多次實例化,即在同一個任務中可以存在多個activity的實例,每個實例都會處理一個Intent對象。如果Activity A的啟動模式為standard,并且A已經啟動,在A中再次啟動Activity A,即調用startActivity(new Intent(this,A.class)),會在A的上面再次啟動一個A的實例,即當前的桟中的狀態為A--&gt;A。 ![](http://www.jcodecraeer.com/uploads/20150520/1432087372621766.jpg) ![](http://www.jcodecraeer.com/uploads/20150520/1432087374604123.jpg) ### singleTop模式: 如果一個以singleTop模式啟動的Activity的實例已經存在于任務棧的棧頂, 那么再啟動這個Activity時,不會創建新的實例,而是重用位于棧頂的那個實例, 并且會調用該實例的**onNewIntent()**方法將Intent對象傳遞到這個實例中。 舉例來說,如果A的啟動模式為singleTop,并且A的一個實例已經存在于棧頂中, 那么再調用startActivity(new Intent(this,A.class))啟動A時, 不會再次創建A的實例,而是重用原來的實例,并且調用原來實例的onNewIntent()方法。 這時任務棧中還是這有一個A的實例。如果以singleTop模式啟動的activity的一個實例 已經存在與任務棧中,但是不在棧頂,那么它的行為和standard模式相同,也會創建多個實例。 ![](http://www.jcodecraeer.com/uploads/20150520/1432087389219419.jpg) ### singleTask模式: 只允許在系統中有一個Activity實例。如果系統中已經有了一個實例, 持有這個實例的任務將移動到頂部,同時intent將被通過onNewIntent()發送。 如果沒有,則會創建一個新的Activity并置放在合適的任務中。 ![](http://www.jcodecraeer.com/uploads/20150520/1432087394416117.jpg) 官方文檔中提到的一個問題: > 系統會創建一個新的任務,并將這個Activity實例化為新任務的根部(root) 這個則需要我們對taskAffinity進行設置了,使用taskAffinity后的解雇: ![](http://www.jcodecraeer.com/uploads/20150520/1432087640888692.jpg) ![](http://www.jcodecraeer.com/uploads/20150520/1432087642408027.jpg) ### singleInstance模式 保證系統無論從哪個Task啟動Activity都只會創建一個Activity實例,并將它加入新的Task棧頂 也就是說被該實例啟動的其他activity會自動運行于另一個Task中。 當再次啟動該activity的實例時,會重用已存在的任務和實例。并且會調用這個實例 的onNewIntent()方法,將Intent實例傳遞到該實例中。和singleTask相同, 同一時刻在系統中只會存在一個這樣的Activity實例。 ![](http://www.jcodecraeer.com/uploads/20150520/1432087655129646.jpg) ## 5.Activity拾遺 對于Activity可能有些東西還沒講到,這里預留一個位置,漏掉的都會在這里補上! 首先是群友珠海-坤的建議,把開源中國的Activity管理類也貼上,嗯,這就貼上,大家可以直接用到 項目中~ ### 1)開源中國客戶端Activity管理類: ``` package net.oschina.app; import java.util.Stack; import android.app.Activity; import android.app.ActivityManager; import android.content.Context; public class AppManager { private static Stack<Activity> activityStack; private static AppManager instance; private AppManager(){} /** * 單一實例 */ public static AppManager getAppManager(){ if(instance==null){ instance=new AppManager(); } return instance; } /** * 添加Activity到堆棧 */ public void addActivity(Activity activity){ if(activityStack==null){ activityStack=new Stack<Activity>(); } activityStack.add(activity); } /** * 獲取當前Activity(堆棧中最后一個壓入的) */ public Activity currentActivity(){ Activity activity=activityStack.lastElement(); return activity; } /** * 結束當前Activity(堆棧中最后一個壓入的) */ public void finishActivity(){ Activity activity=activityStack.lastElement(); finishActivity(activity); } /** * 結束指定的Activity */ public void finishActivity(Activity activity){ if(activity!=null){ activityStack.remove(activity); activity.finish(); activity=null; } } /** * 結束指定類名的Activity */ public void finishActivity(Class<?> cls){ for (Activity activity : activityStack) { if(activity.getClass().equals(cls) ){ finishActivity(activity); } } } /** * 結束所有Activity */ public void finishAllActivity(){ for (int i = 0, size = activityStack.size(); i < size; i++){ if (null != activityStack.get(i)){ activityStack.get(i).finish(); } } activityStack.clear(); } /** * 退出應用程序 */ public void AppExit(Context context) { try { finishAllActivity(); ActivityManager activityMgr= (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); activityMgr.restartPackage(context.getPackageName()); System.exit(0); } catch (Exception e) { } } } ``` ## 本節小結: 好的,本節就到這里,東西都比較苦澀難懂,暫時知道下即可,總結下Task進行整體調度的 相關操作吧: > * 按Home鍵,將之前的Task切換到后臺 > * 長按Home鍵,會顯示出最近執行過的Task列表 > * 在Launcher或HomeScreen點擊app圖標,開啟一個新Task,或者是將已有的Task調度到前臺 > * 啟動singleTask模式的Activity時,會在系統中搜尋是否已經存在一個合適的Task,若存在,則會將這個Task調度到前臺以重用這個Task。如果這個Task中已經存在一個要啟動的Activity的實例,則清除這個實例之上的所有Activity,將這個實例顯示給用戶。如果這個已存在的Task中不存在一個要啟動的Activity的實例,則在這個Task的頂端啟動一個實例。若這個Task不存在,則會啟動一個新的Task,在這個新的Task中啟動這個singleTask模式的Activity的一個實例。 > * 啟動singleInstance的Activity時,會在系統中搜尋是否已經存在一個這個Activity的實例,如果存在,會將這個實例所在的Task調度到前臺,重用這個Activity的實例(該Task中只有這一個Activity),如果不存在,會開啟一個新任務,并在這個新Task中啟動這個singleInstance模式的Activity的一個實例。 好的本節就到這里,關于Task與Activity加載模式的東西還是比較復雜的,下面給大家貼下編寫該文的 時候的一些參考文獻,可以自己看看~ ## 參考文獻: * 1.[Tasks and Back Stack](http://developer.android.com/intl/zh-cn/guide/components/tasks-and-back-stack.html#ManagingTasks) * 2.[理解android中Activity和Task的關系](http://my.oschina.net/MrGuan/blog/75392) * 3.[Activity啟動模式圖文詳解:standard, singleTop, singleTask 以及 singleInstance](http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0520/2897.html) * 4.[Understand Android Activity's launchMode: standard, singleTop, singleTask and singleInstance](http://inthecheesefactory.com/blog/understand-android-activity-launchmode/en) * 5.[Android中Activity四種啟動模式和taskAffinity屬性詳解](http://blog.csdn.net/zhangjg_blog/article/details/10923643) * 6.[Android的Activity和Tasks詳解](http://blog.csdn.net/infsafe/article/details/5666964) * 7.[Activity的四種啟動模式和onNewIntent()](http://gundumw100.iteye.com/blog/2160467) * 8.[譯:Android任務和返回棧完全解析,細數那些你所不知道的細節](http://blog.csdn.net/guolin_blog/article/details/41087993)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看