<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>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                書接上文,App啟動一共有七個階段,上篇文章篇幅所限,我們只看了第一階段,接下來講剩余的六個階段,仍然是拿斗魚App舉例子。 簡單回顧一下第一階段的流程,就是Launcher向AMS發送一個跨進程通信,通過AMN/AMP,告訴AMS,我要啟動斗魚App。 畫一個圖,描述一下啟動App所經歷的7個階段: ![](http://images2015.cnblogs.com/blog/13430/201705/13430-20170519225853353-1638311589.png) #### **第2階段 AMS處理Launcher傳過來的信息** ~~~ class ActivityManagerProxy implements IActivityManager { ................................. public int startActivity(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeStrongBinder(caller != null ? caller.asBinder() : null); data.writeString(callingPackage); intent.writeToParcel(data, 0); data.writeString(resolvedType); data.writeStrongBinder(resultTo); data.writeString(resultWho); data.writeInt(requestCode); data.writeInt(startFlags); .................................. } } ~~~ 這個階段主要是Binder的Server端在做事情。因為我們是沒有機會修改Binder的Server端邏輯的,所以這個階段看起來非常枯燥,我盡量說的簡單些。 首先Binder,也就是AMN/AMP,和AMS通信,肯定每次是做不同的事情,就比如說這次Launcher要啟動斗魚App,那么會發送類型為START_ACTIVITY——TRANSACTION的請求給AMS,同時會告訴AMS要啟動哪個Activity。 AMS說,好,我知道了,然后它會干一件很有趣的事情,就是檢查斗魚App中的Manifest文件,是否存在要啟動的Activity。如果不存在,就拋出Activity not found的錯誤,各位做App的同學對這個異常應該再熟悉不過了,經常寫了個Activity而忘記在Manifest中聲明了,就報這個錯,就是因為AMS在這里做檢查。不管是新啟動一個App的首頁,還是在App內部跳轉到另一個Activity,都會做這個檢查。 但是Launcher還活著啊,所以接下來AMS會通知Launcher,哥們兒沒你什么事了,你“停薪留職”吧。那么AMS是通過什么途徑告訴Launcher的呢? 前面講過,Binder的雙方進行通信是平等的,誰發消息,誰就是Client,接收的一方就是Server。Client這邊會調用Server的代理對象。 對于從Launcher發來的消息,通過AMS的代理對象AMP,發送給AMS。 那么當AMS想給Launcher發消息,又該怎么辦呢?前面不是把Launcher以及它所在的進程給傳過來了嗎?它在AMS這邊保存為一個ActivityRecord對象,這個對象里面有一個ApplicationThreadProxy,單單從名字看就出賣了它,這就是一個Binder代理對象。它的Binder真身,也就是ApplicationThread。 站在AIDL的角度,來畫這張圖,是這樣的: ![](http://images2015.cnblogs.com/blog/13430/201705/13430-20170519225921916-810851677.png) 所以結論是,AMS通過ApplicationThreadProxy發送消息,而App端則是通過ApplicationThread來接收這個消息。 #### **第3階段 Launcher去休眠,然后通知AMS,我真的已經“停薪留職”了,沒有吃空餉** ![](http://images2015.cnblogs.com/blog/13430/201705/13430-20170519225928432-1563080021.png) ApplicationThread(簡稱APT),它和ApplicationThreadProxy(簡稱ATP)的關系,我們在第三階段已經介紹過了。 APT接收到來自AMS的消息后,就調用ActivityThread的sendMessage方法,向Launcher的主線程消息隊列發送一個PAUSE_ACTIVITY消息。 前面說過,ActivityThread就是主線程(UI線程) 看到下面的代碼是不是很親切? ![](http://images2015.cnblogs.com/blog/13430/201705/13430-20170519225946869-1315230205.png) 發送消息是通過一個名為H的Handler類的完成的,這個H類的名字真特么有個性,想記不住都難。 做App的同學都知道,繼承自Handler類的子類,就要實現handleMessage方法,這里是一個switch…case語句,處理各種各樣的消息,PAUSE_ACTIVITY消息只是其中一種,由此也能預見到,AMS給Activity發送的所有消息,以及給其它三大組件發送的所有消息,都從H這里經過,為什么要強調這一點呢,既然四大組件都走這條路,那么這里就可以做點手腳,從而做插件化技術,這個我們以后介紹插件化技術的時候會講到。 ![](http://images2015.cnblogs.com/blog/13430/201705/13430-20170519225957400-731726279.png) H對于PAUSE_ACTIVITY消息的處理,如上面的代碼,是調用ActivityThread的handlePauseActivity方法。這個方法干兩件事: * ActivityThread里面有一個mActivities集合,保存當前App也就是Launcher中所有打開的Activity,把它找出來,讓它休眠。 * 通過AMP通知AMS,我真的休眠了。 你可能會找不到H和APT這兩個類文件,那是因為它們都是ActivityThread的內嵌類。 至此,Launcher的工作完成了。你可以看到在這個過程中,各個類都起到了什么作用。蕓蕓眾生,粉墨登場: * APT * ActivityThread * H #### **第4階段 AMS啟動新的進程** 接下來又輪到AMS做事了,你們會發現我不太喜歡講解AMS的流程,甚至都不畫UML圖,因為這部分邏輯和App開發人員關系不是很大,我盡量說的簡單一些,把流程說清楚就好。 AMS接下來要啟動斗魚App的首頁,因為斗魚App不在后臺進程中,所以要啟動一個新的進程。這里調用的是Process.start方法,并且指定了ActivityThread的main函數為入口函數。 ![](http://images2015.cnblogs.com/blog/13430/201705/13430-20170519230007713-577694475.png) #### **第5階段 新的進程啟動,以ActivityThread的main函數作為入口** ![](http://images2015.cnblogs.com/blog/13430/201705/13430-20170519230017916-541390106.png) 啟動新進程,其實就是啟動一個新的App。 在啟動新進程的時候,為這個進程創建ActivityThread對象,這就是我們耳熟能詳的主線程(UI線程)。 創建好UI線程后,立刻進入ActivityThread的main函數,接下來要做2件具有重大意義的事情: * 1)創建一個主線程Looper,也就是MainLooper。看見沒,MainLooper就是在這里創建的。 * 2)創建Application。記住,Application是在這里生成的。 App開發人員對Application非常熟悉,因為我們可以在其中寫代碼,進行一些全局的控制,所以我們通常認為Application是掌控全局的,其實Application的地位在App中并沒有那么重要,它就是一個Context上下文,僅此而已。 App中的靈魂是ActivityThread,也就是主線程,只是這個類對于App開發人員是訪問不到的——使用反射倒是可以修改這個類的一些行為。 創建新App的最后,就是告訴AMS,我啟動好了,同時把自己的ActivityThread對象發送給AMS,從此以后,AMS的電話簿中就多了這個新的App的登記信息,AMS以后向這個App發送消息,就通過這個ActivityThread對象。 #### **第6階段 AMS告訴新App啟動哪個Activity** AMS把傳入的ActivityThread對象,轉為一個ApplicationThread對象,用于以后和這個App跨進程通信。還記得APT和ATP的關系嗎?這就又回到第2階段的那張關系圖了。 還記得第1階段,Launcher發送給AMS要啟動斗魚App的哪個Activity嗎?這個信息被AMS存下來了。 那么在第6階段,AMS從過去的記錄中翻出來要啟動哪個Activity,然后通過ATP告訴App。 #### **第7階段 啟動斗魚首頁Activity** ![](http://images2015.cnblogs.com/blog/13430/201705/13430-20170519230029494-413774325.png) 畢其功于一役,盡在第7階段。這是最后一步。 App,這個Binder的另一端,通過APT接收到AMS的消息,仍然是在H的handleMessage方法的switch語句中處理,只不過,這次消息的類型是LAUNCH_ACTIVITY: ![](http://images2015.cnblogs.com/blog/13430/201705/13430-20170519230047322-2090810570.png) ActivityClientRecord是什么?這是AMS傳遞過來的要啟動的Activity。 還是這里,我們仔細看那個getPackageInfoNoCheck方法,這個方法會提取Apk中的所有資源,然后設置給r的packageInfo屬性。這個屬性的類型很有名,叫做LoadedApk。各位記住這里,這個地方可以干壞事,也是插件化技術滲入的一個點。 在H的這個分支中,又反過來回調ActivityThread的handleLaunchActivity方法,你要是覺得很繞那就對了。其實我一直覺得,ActivityThread和H合并成一個類也沒問題。 ![](http://images2015.cnblogs.com/blog/13430/201705/13430-20170519230101088-869045714.png) 重新看一下這個過程,每次都是APT執行ActivityThread的sendMessage方法,在這個方法中,把消息拼裝一下,然后扔個H的swicth語句去分析,來決定要執行ActivityThread的那個方法。每次都是這樣,習慣就好了。 handleLaunchActivity方法都做哪些事呢? * 1)通過Instrumentation的newActivity方法,創建出來要啟動的Activity實例。 * 2)為這個Activity創建一個上下文Context對象,并與Activity進行關聯。 * 3)通過Instrumentation的callActivityOnCreate方法,執行Activity的onCreate方法,從而啟動Activity。看到這里是不是很熟悉很親切? 至此,App啟動完畢。這個流程是經過了很多次握手, App和ASM,頻繁的向對方發送消息,而發送消息的機制,是建立在Binder的基礎之上的。
                  <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>

                              哎呀哎呀视频在线观看