日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

前言

上篇文章寫到 Service 的啟動過程; 相對來說Activity的啟動過程比Service的啟動過程更為復雜,其一Activity的生命周期方法比Service多,其二Activity具有啟動模式和返回棧; 寫本文的目的在于更清晰的梳理Activity的啟動過程,加強自己的內功修煉,博客粉絲日益增多,力在以最簡單的方式讓大家理解,跟大家一起學習

一、Binder的基本理解

Activity的啟動有多次IPC過程,所以Binder屬于預備知識,幫助我們更好理解系統的C/S的這種架構模式

二、Activity啟動的雙向IPC過程

一般Android各個應用進程的啟動都以這樣一條路線,init進程 –> Zygote進程 –> SystemServer進程 –>各種應用進程

  • Init進程:linux的根進程,Android系統是基于Linux系統的,因此可以算作是整個android操作系統的第一個進程;
  • Zygote進程是所有應用進程的父進程,所有的應用進程都是它孵化出來的;
  • SystemServer進程含有一些核心的服務,比如ActivityManagerService,PackageManagerService,WindowManagerService等;
  • 各種應用進程:啟動自己編寫的客戶端應用時,有自己的虛擬機與運行環境。

由此可知應用的第一個Activity的啟動是多個進程相互配合的結果,多個進程相互配合就少不了使用Binder進行IPC了,現在看一次IPC調用的過程是怎樣的。

 

上圖大概說明了一次IPC的過程,或許你現在對里面各個類還不是很清楚,沒關系,大致了解一下

ActivityManagerService (下文簡稱AMS),AMS是Android中最核心的服務,實現了ActivityManager,主要負責系統中四大組件的啟動、切換、調度及應用進程的管理和調度等工作,AMS提供了一個ArrayList mHistory來管理所有的Activity,Activity在AMS中的形式是ActivityRecord,Task在AMS中的形式為TaskRecord,進程在AMS中的管理形式為ProcessRecord,它在Android中特別重要

ActivityManagerNative (下文簡稱AMN):由于AMS是系統核心服務在SystemServer進程里面,很多API不能直接開放供客戶端使用,所以需要通過IPC的方式,具體是這樣的,ActivityManager類內部調用AMN的getDefault函數得到一個ActivityManagerProxy對象,通過它可與AMS通信

ActivityManagerProxy (下文簡稱AMP):AMP是AMS在客戶端進程的一個代理,通過AMP里面的方法請求AMS

Instrumentation: Instrumentaion是一個工具類,一個大管家。當它被啟用時,系統先創建它,再通過它來創建其他組件;另外,系統和組件之間的交互也將通過Instrumentation來傳遞,這樣,Instrumentation就能監測系統和這些組件的交互情況了。在實際使用中,我們可以創建Instrumentation的派生類來進行相應的處理。Android中Junit的使用到了Intrstrumentation

OK,現在我們知道,Activity是如何向AMS發出startActivity這個請求了,這意味著Activity可以與AMS進行通信,但是AMS卻不能與Activity通信,Binder是單向的,所以在Activity發出請求之后,AMS需要通知Activity發生狀態改變,要做到這一點,自然就在AMS到Activity這個過程建立一個Binder,如下:

 

大致過程就是,SystemServer進程在收到請求后,再通過IPC向應用進程發送scheduleLaunchActivity請求,應用進程的binder線程(ApplicationThread)在收到請求后,通過handler向主線程發送LAUNCH_ACTIVITY消息,主線程在收到Message后,創建目標Activity,并回調Activity.onCreate()等方法

對上面的理解不是太明白,在看下面這張圖,簡單多了;AMS到Activity這個過程建立了一個Binder,Activity到AMS這個過程也建立了一個Binder,這就能相互通信了

 

上圖就是Activity與AMS之間的雙向Binder連接, (備注:這個就是理解Activity啟動流程的指南針,不記住這個,復雜的啟動流程會讓你暈頭轉向);Activity用IActivityManager提供的API向AMS提出執行某個動作的請求(本例中是啟動RemoteService),AMS通過IApplicationThread提供的API來控制Activity所在的應用程序,這些API包括schedulePauseActivity()、scheduleStopActivity()等

IActivityManager接口定義的API,啟動四大組件的等多種請求都在里面

 

IApplicationThread接口定義的API,一看就比IActivityManager高逼格一點,IActivityManager好多方法是start開頭,表示去AMS請求,IApplicationThread以schedule開頭,表示對Activity進行調度

 

分析到這里,我們不知不覺間忽略了兩個問題,那就是啟動Activity至少需要兩個前提

第一是,應用進程存在,第二AMS已經初始化完畢; 在調用startActivity方法時候,如果我們的應用進程不存在,Activity能啟動嗎,當然是不能的,比如點擊桌面圖標的時候,這個時候需要先創建進程。關于Zygote孵化應用進程,這個暫時不說,先看看AMS服務注冊

三、AMS服務注冊

先忽略 Activity調用ActivityManagerService啟動應用,直接從SystemServer的main方法說起

 /**
    * The main entry point from zygote.
    */
   public static void main(String[] args) {
       new SystemServer().run();
   }

run方法中,調用了startBootstrapServices

 private void startBootstrapServices() {
      
       ......
       //啟動AMS服務
       Installer installer = mSystemServiceManager.startService(Installer.class);

       //請注意這里參數是Lifecycle,因為AMS是在Lifecycle里面new出來的
       mactivityManagerService = mSystemServiceManager.startService(
               ActivityManagerService.Lifecycle.class).getService();
       mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
       mActivityManagerService.setInstaller(installer);

       mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);

       mActivityManagerService.initPowerManagement();

        ......
       mActivityManagerService.setSystemProcess();
     ......
}
 public SystemService startService(String className) {
       final Class<SystemService> serviceClass;
       try {
           serviceClass = (Class<SystemService>)Class.forName(className);
       } catch (ClassNotFoundException ex) {
           Slog.i(TAG, "Starting " + className);
       }
       return startService(serviceClass);
   }

繼續

public <T extends SystemService> T startService(Class<T> serviceClass) {
       try {
           final String name = serviceClass.getName();
           // 1、創建服務
           final T service;
           try {
               Constructor<T> constructor = serviceClass.getConstructor(Context.class);
             // 如果傳進來的是ActivityManagerService.Lifecycle對象,那么ActivityManagerService就能被創建
               service = constructor.newInstance(mContext);
           } catch (InstantiationException ex) {
               throw new RuntimeException("Failed to create service " + name
                       + ": service could not be instantiated", ex);
           }
           // 2、注冊服務
           mServices.add(service);

           // 3、啟動服務
           try {
               service.onStart();
           } catch (RuntimeException ex) {
               throw new RuntimeException("Failed to start service " + name
                       + ": onStart threw an exception", ex);
           }
           return service;
       } finally {
           Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
       }
   }
ActivityManagerService.JAVA

  public static final class Lifecycle extends SystemService {
       private final ActivityManagerService mService;

       public Lifecycle(Context context) {
           super(context);
         //ActivityManagerService被new出來了
           mService = new ActivityManagerService(context);
       }

       @Override
       public void onStart() {
         //  啟動
           mService.start();
       }

       public ActivityManagerService getService() {
           return mService;
       }
   }
 private void start() {
       Process.removeAllProcessGroups();
       mProcessCpuThread.start();

       mBatteryStatsService.publish(mContext);
       mAppOpsService.publish(mContext);
       Slog.d("AppOps", "AppOpsService published");
       LocalServices.addService(ActivityManagerInternal.class, new LocalService());
   }

回到 startBootstrapServices里面調用的
mActivityManagerService.setSystemProcess();

public void setSystemProcess() {
       try {
           ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
           ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats);
           ServiceManager.addService("meminfo", new MemBinder(this));
           ServiceManager.addService("gfxinfo", new GraphicsBinder(this));
           ServiceManager.addService("dbinfo", new DbBinder(this));
           ......


      // 設置application info LoadedApkinfo 有關 framework-res.apk
       ApplicationInfo info = mContext.getPackageManager().getApplicationInfo( "android", STOCK_PM_FLAGS);
       mSystemThread.installSystemApplicationInfo(info, getClass().getClassLoader());
       
       //給SystemServer進程創建ProcessRecord,adj值,就是將SystemServer進程加入到AMS進程管理機制中,跟應用進程一致
       synchronized (this) {
           ProcessRecord app = newProcessRecordLocked(info, info.processName, false, 0);
           app.persistent = true;
           app.pid = MY_PID;
           app.maxAdj = ProcessList.SYSTEM_ADJ;
           app.makeActive(mSystemThread.getApplicationThread(), mProcessStats);
           synchronized (mPidsSelfLocked) {
               mPidsSelfLocked.put(app.pid, app);
           }
           updateLruProcessLocked(app, false, null);
           updateOomAdjLocked();
 }

ServiceManager這里面注冊了很多的服務,可通過dumpsys <服務名>命令查看。比如查看CPU信息命令dumpsys cpuinfo,查看graphics信息命令dumpsys gfxinfo

在Android中所有的核心服務,并不是直接給上層使用,都先交給ServiceManager管理,上層使用的時候可以從ServiceManager獲取,ServiceManager相當于一個路由作用。現在來看一張經典的圖。其中注冊服務,獲取服務以及使用服務,每一次都是一個完整的Binder IPC過程,可見理解Binder是多么的重要啊。關于AMS啟動得深入了解

 

  • 注冊服務:首先AMS注冊到ServiceManager。AMS所在進程(SystemServer)是客戶端,ServiceManager是服務端
  • 獲取服務:Client進程使用AMS前,須先向ServiceManager中獲取AMS的代理類AMP。該過程。AMP所在進程(應用進程)是客戶端,ServiceManager是服務端
  • 使用服務: app進程根據得到的代理類AMP,便可以直接與AMS所在進程交互。該過程,AMP所在進程(應用進程)是客戶端,AMS所在進程(SystemServer)是服務端

 

最后我想說:

學習沒有捷徑可言,我們要注意記學習,不僅要記,還要寫心得體會,文字筆記、畫圖、總結等,方式很多,但是一定要自己認真去做,不要太相信自己的記憶,只有反復記憶,加深理解才行

同時,對于程序員而言,不單單是死記硬背,我們有更好的方式去學習,比如寫demo去驗證。復習知識點時,要及時跟你做過的項目結合起來,這樣在面試時就知道怎么聊了,由項目講到知識點,由一個知識點串聯到另一個知識點。復習到一定階段,可以嘗試著去把這些東西串聯起來,由點及面,形成知識體系

對于程序員來說,要學習的知識內容、技術有太多太多,要想不被環境淘汰就只有不斷提升自己,從來都是我們去適應環境,而不是環境來適應我們

技術是無止境的,你需要對自己提交的每一行代碼、使用的每一個工具負責,不斷挖掘其底層原理,才能使自己的技術升華到更高的層面

Android 架構師之路還很漫長,與君共勉

分享到:
標簽:Android
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定