對象的大小。Intent 中的 Bundle 是使用 Binder 機制進行數據傳送的。能使用的 Binder 的緩衝區是有大小限制的(有些手機是 2 M),而一個進程默認有 16 個 Binder 線程,因此一個線程能佔用的緩衝區就更小了(有人之前作過測試,大約一個線程能夠佔用 128 KB)。可使用 EventBus 來傳遞數據,而不是直接使用 Intent 進行傳遞。java
當 Activity 被銷燬的時候回調用 onSaveInstanceState()
方法來存儲當前的狀態。這樣當 Activity 被重建的時候,能夠在 onCreate()
和 onRestoreInstanceState()
中恢復狀態。android
對於 targetAPI 爲 28 及之後的應用,該方法會在 onStop()
方法以後調用,對於以前的設備,這方法會在 onStop()
以前調用,可是沒法肯定是在 onPause()
以前仍是以後調用。c++
onRestoreInstanceState()
方法用來恢復以前存儲的狀態,它會在 onStart()
和 onPostCreate()
之間被調用。此外,你也能夠直接在 onCreate()
方法中進行恢復,可是基於這個方法調用的時機,若是有特別需求,能夠在這個方法中進行處理。git
FLAG_ACTIVITY_NEW_TASK
。這樣新啓動的 Acitivyt 將會建立一個新的棧。onNewIntent()
。常見的應用場景是從通知打開 Activity 時。onNewIntent()
方法。Android 下拉通知欄不會影響 Activity 的生命週期方法。github
彈出 Dialog,生命週期:實際上是否彈出 Dialog,並不影響 Activity 的生命週期,因此這時和正常啓動時 Activity 的生命回調方法一致: onCreate() -> onStart() -> onResume()
。面試
這裏咱們總結一下在實際的使用過程當中可能會遇到的一些 Acitivity 的生命週期過程:算法
onPause()->onStop()
。由於此時 Activity 已經變成不可見了,固然,若是新打開的 Activity 用了透明主題,那麼 onStop() 不會被調用,所以原來的 Activity 只是不能交互,可是仍然可見。onRestart()->onStart()-onResume()
。此時是從 onStop() 經 onRestart() 回到 onResume() 狀態。onPause()->onStop()->onDestroy()
。具體地,當存在兩個 Activity,分別是 A 和 B 的時候,在各類狀況下,它們的生命週期將會通過:數據庫
A.onPause()->B.onCreate()->B.onStart()->B.onResume->A.onStop()
。B.onPause()->A.onRestart()->A.onStart()->A.onResume()->B.onStop()->B.onDestroy()
。A.onPause()->A.onStop()->A.onDestroy()
。A.onPause()->A.onStop()
。因而可知,Back 鍵和 Home 鍵主要區別在因而否會執行 onDestroy()。android:configChanges
時,切屏會從新調用各個生命週期,切橫屏時會執行一次,切豎屏時會執行兩次。android:configChanges=「orientation」
時,切屏仍是會從新調用各個生命週期,切橫、豎屏時只會執行一次。android:configChanges=「orientation|keyboardHidden」
時,切屏不會從新調用各個生命週期,只會執行 onConfiguration() 方法。onActivityResult()
+ setResult()
AlertDialog 是 Dialog 的子類,因此它包含了 Dialog 類的不少屬性和方法。是彈出對話框的主要方式,對話框分紅支持包的和非支持包的,UI 效果上略有區別。設計模式
AlertDialog 與 PopupWindow 之間最本質的差別在於:緩存
AlertDialog 是非阻塞式對話框;而PopupWindow 是阻塞式對話框
。AlertDialog 彈出時,後臺還能夠作事情;PopupWindow 彈出時,程序會等待,在PopupWindow 退出前,程序一直等待,只有當咱們調用了 dismiss()
方法的後,PopupWindow 退出,程序纔會向下執行。咱們在寫程序的過程當中能夠根據本身的須要選擇使用 Popupwindow 或者是 Dialog.二者最根本的區別在於有沒有新建一個 window
,PopupWindow 沒有新建,而是經過 WMS 將 View 加到 DecorView;Dialog 是新建了一個 window (PhoneWindow),至關於走了一遍 Activity 中建立 window 的流程。Activity 與 Dialog 相似,都會使用 PhoneWindow 來做爲 View 的容器。Activity 也能夠經過設置主題爲 Dialog 的來將其做爲對話框來使用。Dialog 也能夠經過設置 Theme 來表現得像一個 Activity 同樣做爲整個頁面。但 Activity 具備生命週期,而且它的生命週期歸 AMS 管,而 Dialog 不具備生命週期,它歸 WMS 管。
前提是是否跨進程,若是不跨進程的話,EventBus 和 靜態變量都能傳遞信息,不然須要 IPC 才行:
oneway
來定義回調的接口,而後在方法中傳入回調便可。也可使用 Messenger,向遠程發送信息的時候,附帶本地的 Messenger,而後遠程獲取本地的 Messenger 而後向其發送信息便可,詳見 IPC 相關一文:《Android 高級面試-2:IPC 相關》startService()
的方式關於 Activity 相關的內容能夠參考筆者的文章:《Android 基礎回顧:Activity 基礎》
startService()
的時候執行的方法依次爲 onCreate()->onStartCommand()
;當 Service 關閉的時候調用 onDestory()
。bindService()
的時候,執行的方法爲 onCreate()->onBind()
;解除綁定的時候會執行 onUnbind()->onDestory()
。startService(intent)
的時候,會調用該 Service 中的 onCreate()
和onStartCommand()
方法。startService(intent)
的時候,只會調用該 Service 中的 onStartCommand()
方法。(所以已經建立了服務,因此不須要再次調用 onCreate()
方法了)。bindService()
方法的第三個參數是一個標誌位,這裏傳入 BIND_AUTO_CREATE
表示在Activity 和 Service 創建關聯後自動建立 Service,這會使得 MyService 中的 onCreate()
方法獲得執行,但 onStartCommand()
方法不會執行。因此,在上面的程序中當調用了bindService()
方法的時候,會執行的方法有,Service 的 onCreate()
方法,以及 ServiceConnection 的 onServiceConnected()
方法。unbindService()
才行。startService()
,又調用 bindService()
會怎麼樣呢?這時無論你是單獨調用 stopService()
仍是 unbindService()
,Service 都不會被銷燬,必需要將兩個方法都調用 Service 纔會被銷燬。也就是說,stopService()
只會讓 Service 中止,unbindService()
只會讓 Service 和 Activity 解除關聯,一個 Service 必需要在既沒有和任何 Activity 關聯又處理中止狀態的時候纔會被銷燬。分類
getInstance()
獲取一個單例以後就可使用該單例的 registerReceiver()
、unregisterReceiver()
和 sendBroadcast()
等方法來進行操做了。ContentProvider 在 Android 中的做用是對外共享數據,提供了數據訪問接口,用於在不一樣應用程序之間共享數據,同時還能保證被訪問數據的安全性。它一般用來提供一些公共的數據,好比用來查詢文件信息,製做音樂播放器的時候用來讀取系統中的音樂文件的信息。
與 SQLiteDatabase 不一樣,ContentProvider 中的 CRUD 不接收表名參數,而是 Uri 參數。內容 URI 是內容提供器中數據的惟一標識符,包括權限和路徑。
併發訪問時,不管是不一樣的進程仍是同一進程的不一樣線程,當使用 AMS 獲取 Provider 的時候返回的都是同一實例。咱們使用 Provider 來從遠程訪問數據,當 query()
方法運行在不一樣的線程,其實是運行在 Provider 方的進程的 Binder 線程池中。經過 Binder 的線程池來實現多進程和多線程訪問的安全性。
參考:Android ContentProvider的線程安全(一)
Context 的繼承關係以下所示,因此,Android 中的 Context 數量 = Activity 的數量 + Service 的數量 + 1 (Application)
Context 的用途比較廣,好比用來獲取圖片、字符串,顯式對話框等,大部分狀況下,使用哪一個 Context 均可以,少數狀況下只能使用特定的 Context. 好比啓動 Activity 的時候,要求傳入 Activity 的 Context,由於 AMS 須要直到啓動指定 Activity 的 Activity 的棧。通常狀況下,能使用 Application 的 Context 儘可能使用它的,由於它的生命週期更長。
Context 之間使用的是裝飾者設計模式,其中 Context 是一個抽象的類。ContextWrapper 內部實際使用 ContextImpl 實現的,所以全部的邏輯基本是在 ContextImpl 中實現的。而後對於 ContextThemeWrapper,它在 ContextWrapper 的基礎之上又進行了一層裝飾,就是與主題相關的東西。
新版的 Activity 啓動中將 Activity 的各個回調執行的邏輯放在了各個 ClientTransactionItem 中,好比 LaunchActivityItem 表示用來啓動 Activity。 最終執行邏輯的時候是調用它們的 execute() 方法並使用傳入的 ClientTransactionHandler 真正執行任務。而這裏的 ClientTransactionHandler 實際上就是 ActivityThread,因此它將調用到 Activity 的 handleLaunchActivity()
啓動 Activity. 而後程序進入到 performLaunchActivity()
中。這個方法中會建立上面的 Application 和 Activity 對應的 Context:
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
// ...
// 建立 Activity 的 Context
ContextImpl appContext = createBaseContextForActivity(r);
Activity activity = null;
try {
java.lang.ClassLoader cl = appContext.getClassLoader();
// 建立新的 Activity
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
// ...
} catch (Exception e) {
// ... handle exception
}
try {
// 建立應用的 Application
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
if (activity != null) {
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
// Activity 的配置
Configuration config = new Configuration(mCompatConfiguration);
if (r.overrideConfig != null) {
config.updateFrom(r.overrideConfig);
}
// 建立窗口
Window window = null;
if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
window = r.mPendingRemoveWindow;
r.mPendingRemoveWindow = null;
r.mPendingRemoveWindowManager = null;
}
// 關聯 Activity 和 Context
appContext.setOuterContext(activity);
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor, window, r.configCallback);
// ...
// 設置 Activity 的主題
int theme = r.activityInfo.getThemeResource();
if (theme != 0) {
activity.setTheme(theme);
}
// 回調 Activity 的生命週期方法
activity.mCalled = false;
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
r.activity = activity;
}
r.setState(ON_CREATE);
mActivities.put(r.token, r);
} catch (SuperNotCalledException e) {
throw e;
} catch (Exception e) {
// ... handle exception
}
return activity;
}
public Application makeApplication(boolean forceDefaultAppClass, Instrumentation instrumentation) {
// ...
try {
// 建立 Application 的 Context
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
// 關聯 Application 和 Context
appContext.setOuterContext(app);
} catch (Exception e) {
// ... handle exception
}
// ...
return app;
}
複製代碼
聲明瞭四大組件、應用版本、權限等的配置信息,會在解析 APK 的時候由 PMS 進行解析,而後解析的結果會被緩存到 PMS 中。
AsyncTask 是 Android 提供的用來執行異步操做的 API,咱們能夠經過它來執行異步操做,並在獲得結果以後將結果放在主線程當中進行後續處理。
AsyncTask 的缺點是在使用多個異步操做和並須要進行 Ui 變動時,就變得複雜起來(會致使多個 AsyncTask 進行嵌套)。若是有多個地方須要用到 AsyncTask,可能須要定義多個 AsyncTask 的實現。
若是 AsyncTask 以一個非靜態的內部類的形式聲明在 Activity 中,那麼它會持有 Activity 的匿名引用,若是銷燬 Activity 時 AsyncTask 還在執行異步任務的話,Activity 就不能銷燬,會形成內存泄漏。解決方式是,要麼將 AsyncTask 定義成靜態內部類,要麼在 Activity 銷燬的時候調用 cancel()
方法取消 AsyncTask.在屏幕旋轉或 Activity 意外結束時,Activity 被建立,而 AsyncTask 會擁有以前 Activity 的引用,會致使結果丟失。
AsyncTask 在 1.6 以前是串行的,1.6 以後是並行的,3.0 以後又改爲了串行的。不過咱們能夠經過調用 executeOnExecutor()
方法並傳入一個線程池,來讓 AsyncTask 在某個線程池中並行執行任務。
AsyncTask 的源碼就是將一個任務封裝成 Runnable 以後放進線程池當中執行,執行完畢以後調用主線程的 Handler 發送消息到主線程當中進行處理。任務在默認線程池當中執行的時候,會被加入到一個雙端隊列中執行,執行完一個以後再執行下一個,以此來實現任務的串行執行。
瞭解 AsyncTask 的源碼,能夠參考筆者的這篇文章:《Android AsyncTask 源碼分析》
SurfaceView 以及 TextureView 均繼承於 android.view.View
,它們都在獨立的線程
中繪製和渲染,常被用在對繪製的速率要求比較高的應用場景中,用來解決普通 View 由於繪製的時間延遲而帶來的掉幀
的問題,好比用做相機預覽、視頻播放的媒介等。
SurfaceView 提供了嵌入在視圖層次結構內的專用繪圖圖層 (Surface)。圖層 (Surface) 處於 Z 軸
,位於持有 SurfaceView 的窗口以後。SurfaceView 在窗口上開了一個透明的 「洞」 以展現圖面。Surface 的排版顯示受到視圖層級關係的影響,它的兄弟視圖結點會在頂端顯示。注意,若是 Surface 上面有透明控件,那麼每次 Surface 變化都會引發框架從新計算它和頂層控件的透明效果,這會影響性能。SurfaceView 使用雙緩衝,SurfaceView 自帶一個 Surface,這個 Surface 在 WMS 中有本身對應的WindowState,在 SurfaceFlinger 中也會有本身的 Layer。這樣的好處是對這個Surface的渲染能夠放到單獨線程去作。由於這個 Surface 不在 View hierachy 中,它的顯示也不受 View 的屬性控制,因此不能進行平移,縮放等變換,也不能放在其它 ViewGroup 中,一些 View 中的特性也沒法使用。
TextureView 在 Andriod 4.0 以後的 API 中才能使用,而且必須在硬件加速的窗口中。和 SurfaceView 不一樣,它不會在 WMS 中單首創建窗口,而是做爲 View hierachy 中的一個普通 View,所以能夠和其它普通 View 同樣進行移動,旋轉,縮放,動畫等變化。它佔用內存比 SurfaceView 高,在 5.0 之前在主線程渲染,5.0 之後有單獨的渲染線程。
更多內容請參考:Android:解析 SurfaceView & TextureView
事件分發機制等
Activity 的層級:Activity->PhoneWindow->DecorView
當觸摸事件發生的時候,首先會被 Activity 接收到,而後該 Activity 會經過其內部的 dispatchTouchEvent(MotionEvent)
將事件傳遞給內部的 PhoneWindow
;接着 PhoneWindow
會把事件交給 DecorView
,再由 DecorView
交給根 ViewGroup
。剩下的事件傳遞就只在 ViewGroup
和 View
之間進行。
事件分發機制本質上是一個深度優先
的遍歷算法。事件分發機制的核心代碼:
boolean dispatchTouchEvent(MotionEvent e) {
boolean result;
if (onInterceptTouchEvent(e)) { // 父控件能夠覆寫並返回 true 以攔截
result = super.dispatchTouchEvent(e); // 調用 View 中該方法的實現
} else {
for (child in children) {
result = child.dispatchTouchEvent(e); // 這裏的 child 分紅 View 和 ViewGroup 二者情形
if (result) break; // 被子控件消費,中止分發
}
}
return result;
}
複製代碼
對於 dispatchTouchEvent()
方法,在 View 的默認實現中,會先交給 onTouchEvent()
進行處理,若它返回了 true 就消費了,不然根據觸摸的類型,決定是交給 OnClickListener
仍是 OnLongClickListener
繼續處理。
事件分發機制和 View 的體系請參考筆者文章:《View 體系詳解:座標系、滑動、手勢和事件分發機制》,總體上事件分發機制應該分紅三個階段來進行說明:1).從 Activity 到 DecorView 的過程;2).ViewGroup 中的分發的過程;3).交給 View 以後的實現過程。
按照廣度優先算法進行遍歷
ListView 默認緩存一頁的 View,也就是你當前 Listview 界面上有幾個 Item 能夠顯示,,Lstview 就緩存幾個。當現實第一頁的時候,因爲沒有一個 Item 被建立,因此第一頁的 Item 的 getView()
方法中的第二個參數都是爲 null 的。
ViewHolder 一樣也是爲了提升性能。就是用來在緩存使用 findViewById()
方法獲得的控件,下次的時候能夠直接使用它而不用再進行 find
了。
關於 ListView 的 ViewHolder 等的使用,能夠參考這篇文章:ListView 複用和優化詳解
SP,SQLite,ContentProvider,File,Server
MVC (Model-View-Controller, 模型-視圖-控制器),標準的MVC是這個樣子的:
在 Android 開發中,就是指直接使用 Activity 並在其中寫業務邏輯的開發方式。顯然,一方面 Activity 自己就是一個視圖,另外一方面又要負責處理業務邏輯,所以邏輯會比較混亂。這種開發方式不太適合 Android 開發。
MVP (Model-View-Presenter)
實際開發中會像下面這樣定義一個契約接口
public interface HomeContract {
interface IView extends BaseView {
void setFirstPage(List<HomeBean.IssueList.ItemList> itemLists);
void setNextPage(List<HomeBean.IssueList.ItemList> itemLists);
void onError(String msg);
}
interface IPresenter extends BasePresenter {
void requestFirstPage();
void requestNextPage();
}
}
複製代碼
而後讓 Fragment 或者 Activity 等繼承 IView,實例化一個 IPresenter,並在構造方法中將本身引入到 IPresenter 中。這樣 View 和 Presenter 就相互持有了對方的引用。當要發起一個網絡請求的時候,View 中調用 Presenter 的方法,Presenter 拿到告終果以後回調 View 的方法。這樣就使得 View 和 Presenter 只須要關注自身的責任便可。
MVP 缺點:1). Presenter 中除了應用邏輯之外,還有大量的 View->Model,Model->View 的手動同步邏輯,形成 Presenter 比較笨重,維護起來會比較困難;2). 因爲對視圖的渲染放在了 Presenter 中,因此視圖和 Presenter 的交互會過於頻繁;3). 若是 Presenter 過多地渲染了視圖,每每會使得它與特定的視圖的聯繫過於緊密,一旦視圖須要變動,那麼 Presenter 也須要變動了。
MVVM 是 Model-View-ViewModel 的簡寫。它本質上就是 MVC 的改進版。MVVM 就是將其中的 View 的狀態和行爲抽象化,讓咱們將視圖 UI 和業務邏輯分開。
優勢:
關於移動應用架構部份內容能夠參考筆者的文章:《Android 架構設計:MVC、MVP、MVVM和組件化》,另外關於 MVVM 架構設計中的 ViewModel 和 LiveData 的機制能夠參考:《淺談 ViewModel 的生命週期控制》 和 《淺談 LiveData 的通知機制》
startActivity()
-> Process.start()
-> Socket -> (SystemServer) -> Zygote.fork() -> VM,Binder 線程池 -> ActivityThread.main()
Instrumentation.execStartActivity()
-> IApplicationThread+AMS+H
-> 校驗用戶信息等 -> 解析 Intent -> 回調 IApplicationThread.scheduleTransaction()
Android是一個權限分離的系統,這是利用 Linux 已有的權限管理機制,經過爲每個 Application 分配不一樣的 uid 和 gid,從而使得不一樣的 Application 之間的私有數據和訪問(native以及java層經過這種 sandbox 機制,均可以)達到隔離的目的 。與此同時,Android 還在此基礎上進行擴展,提供了 permission 機制,它主要是用來對 Application 能夠執行的某些具體操做進行權限細分和訪問控制,同時提供了 per-URI permission 機制,用來提供對某些特定的數據塊進行 ad-hoc 方式的訪問。
Q:權限管理系統(底層的權限是如何進行 grant 的)
Q:動態權限適配方案,權限組的概念
Q:大致說清一個應用程序安裝到手機上時發生了什麼?
Q:應用安裝過程
應用安裝的時候涉及幾個類,分別時 PackageManager, ApplicationPackageManager 和 PMS. 它們之間的關係是,PackageManager 是一個抽象類,它的具體實現是 ApplicationPackageManager,然後者的全部實現都是靠 PMS 實現的。PMS 是一種遠程的服務,與 AMS 類似,在同一方法中啓動。另外,還有 Installer 它是安裝應用程序的輔助類,它也是一種系統服務,與 PMS 在同一方法中啓動。它會經過 Socket 與遠程的 Installd 創建聯繫。這是由於權限的問題,PMS 只有 system 權限。installd 倒是具備 root 權限。(Installd 的做用好像就是建立一個目錄)
installd是由Android系統init進程(pid=1),在解析init.rc文件的代碼時,經過fork建立用戶空間的守護進程intalld。啓動時,進入監聽socket,當客戶端發送過來請求時,接收客戶端的請求,並讀取客戶端發送過來的命令數據,並根據讀取客戶端命令來執行命令操做。
Android上應用安裝能夠分爲如下幾種方式:
apk的大致流程以下:
普通安裝:
PackagInstaller是安卓上默認的應用程序,用它來安裝普通文件。PackageInstaller調用一個叫作InstallAppProgress的activity來獲取用戶發出的指令。InstallAppProgress會請求Package Manager服務,而後經過installed來安裝包文件。它提供了安裝的頁面和安裝進度相關頁面,咱們平時安裝應用時顯式的就是它。(源碼)
最終的安卓過程則是交給 PMS 的 installPackageLI()
方法來完成,它也會先對 manifest 進行解析,而後將解析的結果添加到 PMS 的緩存中,並註冊四大組件。
若是是第一次安裝的時候就會調用 scanPackageLI()
方法來進行安裝。
按下電源以後,首先加載引導程序 BootLoader 到 RAM;而後,執行引導程序 BootLoader 以把系統 OS 拉起來;接着,啓動 Linux 內核;內核中啓動的第一個用戶進程是 init 進程,init 進程會經過解析 init.rc 來啓動 zygote 服務;Zygote 又會進一步的啓動 SystemServer;在 SystemServer 中,Android 會啓動一系列的系統服務供用戶調用。
Init 進程會啓動以後會解析 init.rc
文件,該文件由固定格式的指令組成,在 AOSP 中有說明它的規則。其中的每一個指令對應系統中的類。在解析文件的時候會將其轉換成對應的類的實例來保存,好比 service 開頭的指令會被解析成 Service 對象。在解析 init.rc
文件以前會根據啓動時的屬性設置加載指定的 rc 文件到系統中。當解析完畢以後系統會觸發初始化操做。它會經過調用 Service 的 start()
方法來啓動屬性服務,而後進入 app_main.cpp
的 main() 方法。這個方法中會根據 service 指令的參數來決定調用 Java 層的 ZygoteInit 仍是 RuntimeInit. 這裏會調用後者的 ZygoteInit 初始化 Zygote 進程。
if (zygote) {
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
} else if (className) {
runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
} else {
app_usage();
}
複製代碼
它調用的方式是經過 runtime 的 start()
方法,而這個 runtime 就是 AndroidRuntime. 可是在執行 Java 類以前得先有虛擬機,因此它會先啓動虛擬機實例,而後再調用 ZygoteInit 的方法。因此,AndroidRuntime 的 start()
方法中主要作了三件事情:1).調用函數 startVM()
啓動虛擬機;2).調用函數 startReg()
註冊 JNI 方法;3).調用 com.android.internal.os.ZygoteInit
類的 main()
函數。
ZygoteInit 用來初始化 Zygote 進程的,它的 main()
函數中主要作了三件事情:
registerZygoteSocket()
函數建立了一個 socket 接口,用來和 AMS 通信;(Android 應用程序進程啓動過程當中,AMS 是經過 Process.start()
函數來建立一個新的進程的,而 Process.start()
函數會首先經過 Socket 鏈接到 Zygote 進程中,最終由 Zygote 進程來完成建立新的應用程序進程,而 Process 類是經過 openZygoteSocketIfNeeded()
函數來鏈接到 Zygote 進程中的 Socket.)startSystemServer()
函數來啓動 SystemServer 組件,Zygote 進程經過 Zygote.forkSystemServer()
函數來建立一個新的進程來啓動 SystemServer 組件;(SystemServer 的 main 方法將會被調用,並在這裏啓動 Binder 中的 ServiceManager 和各類系統運行所需的服務,PMS 和 AMS 等)runSelectLoopMode()
函數進入一個無限循環在前面建立的 socket 接口上等待 AMS 請求建立新的應用程序進程。總結一下:
編譯打包的過程->adb->安裝過程 PMS->應用啓動過程 AMS
Android 高級面試系列文章,關注做者及時獲取更多面試資料,
本系列以及其餘系列的文章均維護在 Github 上面:Github / Android-notes,歡迎 Star & Fork. 若是你喜歡這篇文章,願意支持做者的工做,請爲這篇文章點個贊👍!