都說衣不如新人不如故,技術是學新不學舊的?IPC+view+Handler+線程。

剛剛過去2019,新的一年2020年。都說衣不如新人不如故,技術是學新不學舊的?可是舊的知識不鞏固,根基不固很容易在面試或者實戰遇到很大的問題的

以下知識點PDF版後續可見

更多面試內容等等

更多完整項目下載。未完待續。源碼。圖文知識後續上傳github。
可以點擊關於我聯繫我獲取
https://github.com/xiangjiana/Android-MS

一丶線程篇

1、線程池的好處? 四種線程池的使用場景,線程池的幾個參數的理解?

參考答案
使用線程池的好處是減少在創建和銷燬線程上所花的時間以及系統資源的開銷,解決資源不足的問題。如果不使用線程池,有可能造成系統創建大量同類線程而導致消耗完內存或則“過度切換”的問題,歸納總結就是

  • 重用存在的線程,減少對象創建、消亡的開銷,性能佳。
  • 可有效控制最大併發線程數,提高系統資源的使用率,同時避免過多資源競爭,避免堵塞
  • 提供定時執行、定期執行、單線程、併發數控制等功能。

Android 中的線程池都是直接或間接通過配置
ThreadPoolExecutor 來實現不同特性的線程池.Android 中最常見的類具有不同特性的線程池分別爲:

  • newCachedThreadPool 只有非核心線程,最大線程數非常大,所有線程都活動時會爲新任務創建新線程,否則會利用空閒線程 ( 60s 空閒時間,過了就會被回收,所以線程池中有 0 個線程的可能 )來處理任務.
    優點: 任何任務都會被立即執行(任務隊列SynchronousQuue 相當於一個空集合);比較適合執行大量的耗時較少的任務.

  • newFixedThreadPool 只有核心線程,並且數量固定的,所有線程都活動時,因爲隊列沒有限制大小,新任務會等待執行,當線程池空閒時不會釋放工作線程,還會佔用一定的系統資源。
    優點: 更快的響應外界請求

  • newScheduledThreadPool 核心線程數固定,非核心線程(閒着沒活幹會被立即回收數)沒有限制.
    優點: 執行定時任務以及有固定週期的重複任務

  • newSingleThreadExecutor 只有一個核心線程,確保所有的任務都在同一線程中按序完成
    優點: 不需要處理線程同步的問題

通過源碼可以瞭解到上面的四種線程池實際上還是利用ThreadPoolExecutor 類實現的

  //詳細介紹課參考Executors.java類
  public static ExecutorService newCachedThreadpool () {
         return new ThreadPoolExecutor (0,Integer.MAX_VALUE
                                        60L,TimeUnit.SECONDS,
                                        new SynchronousQueue<Runnable>());
  }
  ThreadPoolExecutor(int corepoolSize,int maxmumpoolSize,
                     long keepAliveTime,TimeUnit unit,
                     Blockingqueue<Runnable>workqueue,RejectedExecutionHandler handler
2、Android 中還了解哪些方便線程切換的類?

參考回答:

  • AsyncTask 底層封裝了線程池和 Handler,便於執行後臺任務以及在子線程中進行 UI 操作。
  • HandlerThread 一種具有消息循環的線程,其內部可使用Handler。
  • IntentService 是一種異步、會自動停止的服務,內部採用HandlerThread
3、 AsyncTask 的原理

參考回答:

  • AsyncTask 中有兩個線程池(SerialExecutor 和THREAD_POOL_EXECUTOR)和一個 Handler(InternalHandler),其中線程池 SerialExecutor 用於任務的排隊,而線程池THREAD_POOL_EXECUTOR 用於真正地執行任務,InternalHandler 用於將執行環境從線程池切換到主線程。
  • 靜態的 Handler 對象,爲了能夠將執行環境切換到主線程,這就要求 這個對象必須在主線程創建。由於靜態成員會在加載類的時候進行初始化,因此這就變相要求 AsyncTask 的類必須在主線程中加載,否則同一個進程中的 AsyncTask 都將無法正常工作。
4、IntentService 有什麼用 ?

IntentService 可用於執行後臺耗時的任務,當任務執行完成後會自動停止,同時由於 IntentService 是服務的原因,不同於普通 Service,IntentService 可自動創建子線程來執行任務,這導致它的優先級比單純的線程要高,不容易被系統殺死,所以IntentService 比較適合執行一些高優先級的後臺任務。

5、直接在 Activity 中創建一個 thread 跟在 service 中創建一個 thread 之間的區別?

參考回答:

  • 在 Activity 中被創建: 該 Thread 的就是爲這個 Activity 服務的,完成這個特定的 Activity 交代的任務,主動通知該 Activity一些消息和事件,Activity 銷燬後,該 Thread 也沒有存活的意義了
  • 在 Service 中被創建: 這是保證最長生命週期的 Thread 的唯一方式,只要整個 Service 不退出,Thread 就可以一直在後臺執行,一般在 Service 的 onCreate()中創建,在 onDestroy()中銷燬。所以,在 Service 中創建的 Thread,適合長期執行一些獨立於 APP 的後臺任務,比較常見的就是:在 Service 中保持與服務器端的長連接。
6、ThreadPoolExecutor 的工作策略 ?

參考回答: ThreadPoolExecutor 執行任務時會遵循如下規則

  • 如果線程池中的線程數量未達到核心線程的數量,那麼會直接啓動一個核心線程來執行任務。
  • 如果線程池中的線程數量已經達到或則超過核心線程的數量,那麼任務會被插入任務隊列中排隊等待執行。
  • 如果在第 2 點無法將任務插入到任務隊列中,這往往是由於任務隊列已滿,這個時候如果在線程數量未達到線程池規定的最大值,那麼會立刻啓動一個非核心線程來執行任務。
  • 如果第 3 點中線程數量已經達到線程池規定的最大值,那麼就拒絕執行此任務,ThreadPoolExecutor 會調用RejectedExecutionHandlerrejectedExecution 方法來通知調用者。
7、Handler、Thread 和 HandlerThread 的差別?

參考回答:

  • Handler: 在 android 中負責發送和處理消息,通過它可以實現其他支線線程與主線程之間的消息通訊。
  • Thread: Java 進程中執行運算的最小單位,亦即執行處理機調度的基本單位。某一進程中一路單獨運行的程序。
  • HandlerThread: 一個繼承自 Thread 的類 HandlerThread,Android 中沒有對 Java 中的 Thread 進行任何封裝,而是提供了一個繼承自 Thread 的類 HandlerThread 類,這個類對 Java的 Thread 做了很多便利的封裝。HandlerThread 繼承於Thread,所以它本質就是個 Thread。與普通 Thread 的差別就在於,它在內部直接實現了 Looper 的實現,這是 Handler 消息機制必不可少的。有了自己的 looper,可以讓我們在自己的線程中分發和處理消息。如果不用 HandlerThread 的話,需要手動去調用 Looper.prepare()Looper.loop()這些方法。
8、ThreadLocal 的原理

參考回答:
ThreadLocal 是一個關於創建線程局部變量的類。使用場景如下所示:

  • 實現單個線程單例以及單個線程上下文信息存儲,比如交易 id 等
  • 實現線程安全,非線程安全的對象使用 ThreadLocal 之後就會變得線程安全,因爲每個線程都會有一個對應的實例。 承載一些線程相關的數據,避免在方法中來回傳遞參數。

當需要使用多線程時,有個變量恰巧不需要共享,此時就不必使用 synchronized 這麼麻煩的關鍵字來鎖住,每個線程都相當於在堆內存中開闢一個空間,線程中帶有對共享變量的緩衝區,通過緩衝區將堆內存中的共享變量進行讀取和操作,ThreadLocal 相當於線程內的內存,一個局部變量。每次可以對線程自身的數據讀取和操作,並不需要通過緩衝區與 主內存中的變量進行交互。並不會像 synchronized 那樣修改主內存的數據,再將主內存的數據複製到線程內的工作內存。ThreadLocal 可以讓線程獨佔資源,存儲於線程內部,避免線程堵塞造成 CPU 吞吐下降。

在每個 Thread 中包含一個 ThreadLocalMapThreadLocalMap 的 key 是 ThreadLocal 的對象,value 是獨享數據。

9、多線程是否一定會高效(優缺點)

參考回答:
多線程的優點:

  • 方便高效的內存共享 - 多進程下內存共享比較不便,且會抵消掉多進程編程的好處
  • 較輕的上下文切換開銷 - 不用切換地址空間,不用更改CR3 寄存器,不清空 TLB
  • 線程上的任務執行完後自動銷燬

多線程的缺點:

  • 開啓線程需要佔用一定的內存空間(默認情況下,每一個線程都佔 512KB)
  • 如果開啓大量的線程,會佔用大量的內存空間,降低程序的性能
  • 線程越多,cpu 在調用線程上的開銷就越大
  • 程序設計更加複雜,比如線程間的通信、多線程的數據共享

綜上得出,多線程不一定能提高效率,在內存空間緊張的情況下反而是一種負擔,因此在日常開發中,應儘量

  • 不要頻繁創建,銷燬線程,使用線程池
  • 減少線程間同步和通信(最爲關鍵)
  • 避免需要頻繁共享寫的數據
  • 合理安排共享數據結構,避免僞共享(false sharing)
  • 使用非阻塞數據結構/算法
  • 避免可能產生可伸縮性問題的系統調用(比如 mmap)
  • 避免產生大量缺頁異常,儘量使用 Huge Page
  • 可以的話使用用戶態輕量級線程代替內核線程
10、多線程中,讓你做一個單例,你會怎麼做

參考回答:

  • 多線程中建立單例模式考慮的因素有很多,比如線程安全 -延遲加載-代碼安全:如防止序列化攻擊,防止反射攻擊(防止反射進行私有方法調用) -性能因素
  • 實現方法有多種,餓漢,懶漢(線程安全,線程非安全),雙重檢查(DCL),內部類,以及枚舉
  //OkHttp例子
  private static volatile OkHttpHelper SInstance;
  
  public static OkHttpHelper getInstance() {
         if (sInstance =null) {
             synchronized (OkHttpHelper.class) {
                if (sInstance =null) {
                    sInstance = new OkHttpHelper();
                }
             }
          }
     return sInstance;
  }
11、除了 notify 還有什麼方式可以喚醒線程

參考回答:

  • 當一個擁有 Object 鎖的線程調用 wait()方法時,就會使當前線程加入 object.wait 等待隊列中,並且釋放當前佔用的 Object鎖,這樣其他線程就有機會獲取這個 Object 鎖,獲得 Object鎖的線程調用 notify()方法,就能在 Object.wait 等待隊列中隨機喚醒一個線程(該喚醒是隨機的與加入的順序無關,優先級高的被喚醒概率會高)
  • 如果調用 notifyAll()方法就喚醒全部的線程。注意:調用notify()方法後並不會立即釋放 object 鎖,會等待該線程執行完畢後釋放 Object 鎖。
12、什麼是 ANR ? 什麼情況會出現 ANR ?如何避免 ? 在不看代碼的情況下如何快速定位出現 ANR 問題所在 ?

參考回答:

  • ANR(Application Not Responding,應用無響應):當操作在一段時間內系統無法處理時,會在系統層面會彈出 ANR 對話框
  • 產生 ANR 可能是因爲 5s 內無響應用戶輸入事件、10s 內未結束BroadcastReceiver、20s 內未結束 Service
  • 想要避免 ANR 就不要在主線程做耗時操作,而是通過開子線程,方法比如繼承 Thread 或實現 Runnable 接口、使用AsyncTask IntentServiceHandlerThread

二丶Handler篇

1、談談消息機制 Handler 作用 ?有哪些要素 ?流程是怎樣的 ?

參考回答:
負責跨線程通信,這是因爲在主線程不能做耗時操作,而子線程不能更新 UI,所以當子線程中進行耗時操作後需要更新 UI時,通過 Handler 將有關 UI 的操作切換到主線程中執行。

具體分爲四大要素

  • Message(消息): 需要被傳遞的消息,消息分爲硬件產生的消息(如按鈕、觸摸)和軟件生成的消息。
  • MessageQueue(消息隊列): 負責消息的存儲與管理,負責管理由 Handler 發送過來的 Message。讀取會自動刪除消息,單鏈表維護,插入和刪除上有優勢。在其 next()方法中會無限循環,不斷判斷是否有消息,有就返回這條消息並移除。
  • Handler(消息處理器): 負責 Message 的發送及處理。主要向消息池發送各種消息事件(Handler.sendMessage())和處理相應消息事件(Handler.handleMessage()),按照先進先出執行,內部使用的是單鏈表的結構。
  • Looper(消息池): 負責關聯線程以及消息的分發,在該線程下從 MessageQueue 獲取 Message,分發給Handler,Looper 創建的時候會創建一個MessageQueue,調用 loop()方法的時候消息循環開
    始,其中會不斷調用 messageQueuenext()方法,當有消息就處理,否則阻塞在 messageQueuenext()方法中。當 Looperquit()被調用的時候會調用messageQueuequit(),此時 next()會返回 null,然後 loop()方法也就跟着退出。

流程:

  • 在主線程創建的時候會創建一個 Looper,同時也會在在Looper 內部創建一個消息隊列。而在創鍵 Handler 的時候取出當前線程的 Looper,並通過該 Looper 對象獲得消息隊列,然後 Handler 在子線程中通過MessageQueue.enqueueMessage 在消息隊列中添加一條 Message。
  • 通過 Looper.loop() 開啓消息循環不斷輪詢調用MessageQueue.next(),取得對應的 Message 並且通過 Handler.dispatchMessage 傳遞給 Handler,最終調用 Handler.handlerMessage 處理消息。
2、一個線程能否創建多個 Handler,Handler 跟 Looper 之間的對應關係 ?

參考回答:

  • 一個 Thread 只能有一個 Looper,一個 MessageQueen,可以有多個 Handler
  • 以一個線程爲基準,他們的數量級關係是: Thread(1) :Looper(1) : MessageQueue(1) : Handler(N)
3、軟引用跟弱引用的區別

參考回答:

  • 軟引用(SoftReference): 如果一個對象只具有軟引用,則內存空間充足時,垃圾回收器就不會回收它;如果內存空間不足了,就會回收這些對象的內存。只要垃圾回收器沒有回收它,該對象就可以一直被程序使用。
  • 弱引用(WeakReference): 如果一個對象只具有弱引用,那麼在垃圾回收器線程掃描的過程中,一旦發現了只具有弱引用的對象,不管當前內存空間足夠與否,都會回收它的內存。
  • 兩者之間根本區別在於: 只具有弱引用的對象擁有更短暫的生命週期,可能隨時被回收。而只具有軟引用的對象只有當內存不夠的時候才被回收,在內存足夠的時候,通常不被回收。
4、Handler 引起的內存泄露原因以及最佳解決方案

參考回答:
**泄露原因:**Handler 允許我們發送延時消息,如果在延時期間用戶關閉了 Activity,那麼該 Activity 會泄露。 這個泄露是因爲 Message 會持有 Handler,而又因爲 Java 的特性,內部類會持有外部類,使得 Activity 會被Handler 持有,這樣最終就導致 Activity 泄露。

**解決方案:**將 Handler 定義成靜態的內部類,在內部持有Activity 的弱引用,並在 AcitivityonDestroy()中調用 handler.removeCallbacksAndMessages(null)及時移除所有消息。

5、爲什麼系統不建議在子線程訪問 UI?

參考回答:
Android 的 UI 控件不是線程安全的,如果在多線程中併發訪問可能會導致 UI 控件處於不可預期的狀態

這時你可能會問爲何系統不對 UI 控件的訪問加上鎖機制呢?因爲

  • 加鎖機制會讓 UI 訪問邏輯變的複雜
  • 加鎖機制會降低 UI 的訪問效率,因爲加鎖會阻塞某些線程的執行
6、Looper 死循環爲什麼不會導致應用卡死?

參考回答:

  • 主線程的主要方法就是消息循環,一旦退出消息循環,那麼你的應用也就退出了,Looer.loop()方法可能會引起主線程的阻塞,但只要它的消息循環沒有被阻塞,能一直處理事件就不會產生 ANR 異常。
  • 造成 ANR 的不是主線程阻塞,而是主線程的 Looper 消息處理過程發生了任務阻塞,無法響應手勢操作,不能及時刷新 UI。
  • 阻塞與程序無響應沒有必然關係,雖然主線程在沒有消息可處理的時候是阻塞的,但是隻要保證有消息的時候能夠立刻處理,程序是不會無響應的。
7、使用 Handler 的 postDealy 後消息隊列會有什麼變化?

參考回答:
如果隊列中只有這個消息,那麼消息不會被髮送,而是計算到時喚醒的時間,先將 Looper 阻塞,到時間就喚醒它。但如果此時要加入新消息,該消息隊列的對頭跟 delay 時間相比更長,則插入到頭部,按照觸發時間進行排序,隊頭的時間最小、隊尾的時間最大

8、可以在子線程直接 new 一個 Handler 嗎?怎麼做?

參考回答:
不可以,因爲在主線程中,Activity 內部包含一個 Looper 對象,它會自動管理 Looper,處理子線程中發送過來的消息。而對於子線程而言,沒有任何對象幫助我們維護 Looper 對象,所以需要我們自己手動維護。所以要在子線程開啓 Handler 要先創建 Looper,並開啓 Looper 循環

  //代碼示例
  new Thread(new Runnable() {
             @Override
             public void run() {
                looper.prepare();
                new Handler() {
                    @Override
                     public void handlerMessage(Message msg) {
                        super.handleMessage(msg);
                     }
                     looper.loop();
                }
     }).start();
9、Message 可以如何創建?哪種效果更好,爲什麼?

參考回答: 可以通過三種方法創建:

  • 直接生成實例 Message m = new Message
  • 通過 Message m = Message.obtain
  • 通過 Message m = mHandler.obtainMessage()

後兩者效果更好,因爲 Android 默認的消息池中消息數量是 10,而後
兩者是直接在消息池中取出一個 Message 實例,這樣做就可以避免多
生成 Message 實例。

三丶IPC

1 丶Android 中進程和線程的關係和區別?

參考回答:

  • 線程是 CPU 調度的 最小單元,同時線程是一種 有限的系統資源
  • 進程一般指一個執行單元,在 PC 和移動設備上一個程序或則一個應用
  • 一般來說,一個 App 程序 至少有一個進程,一個進程 至少有一個線程(包含與被包含的關係), 通俗來講就是,在App 這個工廠裏面有一個進程,線程就是裏面的生產線,但主線程(主生產線)只有一條,而子線程(副生產線)可以有多個
  • 進程有自己獨立的地址空間,而進程中的線程共享此地址空間,都可以 併發執行
2 、如何開啓多進程 ? 應用是否可以開啓 N 個進程 ?

參考回答:

  • AndroidMenifest 中給四大組件指定屬性android:process 開啓多進程模式
  • 在內存允許的條件下可以開啓 N 個進程
3 、爲何需要 IPC ?多進程通信可能會出現的問題?

參考回答:
所有運行在不同進程的四大組件(Activity、Service、Receiver丶ContentProvider)共享數據都會失敗,這是由於 Android 爲每個應用分配了獨立的虛擬機,不同的虛擬機在內存分配上有不同的地址空間,這會導致在不同的虛擬機中訪問同一個類的對象會產生多份副本。比如常用例子( 通過開啓多進程獲取更大內存空間、兩個或則多個應用之間共享數據、微信全家桶)

一般來說,使用多進程通信會造成如下幾方面的問題

  • 靜態成員和單例模式完全失效: 獨立的虛擬機造成
  • 線程同步機制完全實效: 獨立的虛擬機造成
  • SharedPreferences的可靠性下降: 這是因爲 Sp 不支持兩個進程併發進行讀寫,有一定機率導致數據丟失
  • Application 會多次創建: Android 系統在創建新的進程會分配獨立的虛擬機,所以這個過程其實就是啓動一個應用的過程,自然也會創建新的Application
4 丶Android 中 IPC 方式、各種方式優缺點,爲什麼選擇 Binder

參考回答:

與 Linux 上傳統的 IPC 機制,比如 System V,Socket 相比,Binder 好在哪呢?
傳輸效率高、可操作性強: 傳輸效率主要影響因素是內存拷貝的次數,拷貝次數越少,傳輸速率越高。從 Android進程架構角度分析:對於消息隊列、Socket 和管道來說,數據先從發送方的緩存區拷貝到內核開闢的緩存區中,再從內核緩存區拷貝到接收方的緩存區,一共兩次拷貝,如圖:

而對於 Binder 來說,數據從發送方的緩存區拷貝到內核的緩存區,而接收方的緩存區與內核的緩存區是映射到同一塊物理地址的,節省了一次數據拷貝的過程,如圖:

由於共享內存操作複雜,綜合來看,Binder 的傳輸效率是最好的。

實現 C/S 架構方便: Linux 的衆 IPC 方式除了 Socket 以外都不是基於 C/S 架構,而 Socket 主要用於網絡間的通信且傳輸效率較低。Binder 基於 C/S 架構 ,Server 端與Client 端相對獨立,穩定性較好。
安全性高: 傳統 Linux IPC 的接收方無法獲得對方進程可靠的 UID/PID,從而無法鑑別對方身份;而 Binder 機制爲每個進程分配了 UID/PID 且在 Binder 通信時會根據UID/PID 進行有效性檢測。

5 、Binder機制的左右和原理

參考回答:
Linux 系統將一個進程分爲 用戶空間和 內核空間。對於進程之間來說,用戶空間的數據不可共享,內核空間的數據可共享,爲了保證安全性和獨立性,一個進程不能直接操作或者訪問另一個進程,即 Android 的進程是相互獨立、隔離的,這就需要跨進程之間的數據通信方式

一次完整的 Binder IPC 通信過程通常是這樣:

  • 首先 Binder 驅動在內核空間創建一個數據接收緩存區;
  • 接着在內核空間開闢一塊內核緩存區,建立內核緩存區和內核中數據接收緩存區之間的映射關係,以及內核中數據接收緩存區和接收進程用戶空間地址的映射關係;
  • 發送方進程通過系統調用 copyfromuser() 將數據 copy 到內核中的內核緩存區,由於內核緩存區和接收進程的用戶空間存在內存映射,因此也就相當於把數據發送到了接收進程的用戶空間,這樣便完成了一次進程間的通信。
6 、Binder 框架中 ServiceManager的作用

參考回答:

  • Binder 框架 是基於 C/S 架構的。由一系列的組件組成,包括 Client、Server、ServiceManager、Binder 驅動,其中Client、Server、Service Manager 運行在用戶空間,Binder 驅動運行在內核空間
  • Server&Client: 服務器&客戶端。在 Binder 驅動和Service Manager 提供的基礎設施上,進行 Client-Server 之間的通信。
  • ServiceManager(如同 DNS 域名服務器)服務的管理者,將 Binder 名字轉換爲 Client 中對該 Binder的引用,使得 Client 可以通過 Binder 名字獲得Server 中 Binder 實體的引用。
  • Binder 驅動(如同路由器): 負責進程之間 binder通信的建立,傳遞,計數管理以及數據的傳遞交互等底層支持
7丶Bundle 傳遞對象爲什麼需要序列化?Serialzable 和 Parcelable

參考回答:

  • 因爲 bundle 傳遞數據時只支持基本數據類型,所以在傳遞對象時需要序列化轉換成可存儲或可傳輸的本質狀態(字節流)。序列化後的對象可以在網絡、IPC(比如啓動另一個進程的 Activity、Service 和 Reciver)之間進行傳輸,也可以存儲到本地。
  • 序列化實現的兩種方式:實現 Serializable/Parcelable接口。不同點如圖:
8 、講講 AIDL ?原理是什麼?如何優化多模塊都使用 AIDL

參考回答:
AIDL(Android Interface Definition Language,Android接口定義語言):如果在一個進程中要調用另一個進程中對象的方法,可使用 AIDL 生成可序列化的參數,AIDL 會生成一個服務端對象的代理類,通過它客戶端實現間接調用服務端對象的方法

AIDL 的本質是系統提供了一套可快速實現 Binder 的工具。關鍵類和方法:

  • AIDL 接口: 繼承 Interface
  • Stub 類: Binder 的實現類,服務端通過這個類來提供服務。
  • Proxy 類: 服務器的本地代理,客戶端通過這個類調用服務器的方法。
  • asInterface() 客戶端調用,將服務端的返回的Binder 對象,轉換成客戶端所需要的 AIDL 接口類型對象。如果客戶端和服務端位於統一進程,則直接返回 Stub 對象本身,否則返回系統封裝後的Stub.proxy 對象
  • **asBinder():**根據當前調用情況返回代理 Proxy 的Binder 對象。
  • onTransact() 運行服務端的 Binder 線程池中,當客戶端發起跨進程請求時,遠程請求會通過系統底層封裝後交由此方法來處理。
  • transact() 運行在客戶端,當客戶端發起遠程請求的同時將當前線程掛起。之後調用服務端的onTransact()直到遠程請求返回,當前線程才繼續執行。

當有多個業務模塊都需要 AIDL 來進行 IPC,此時需要爲每個模塊創建特定的 aidl 文件,那麼相應的 Service 就會很多。必然會出現系統資源耗費嚴重、應用過度重量級的問題。解決辦法是建立 Binder 連接池,即將每個業務模塊的Binder 請求統一轉發到一個遠程 Service 中去執行,從而避免重複創建 Service。

工作原理: 每個業務模塊創建自己的 AIDL 接口並實現此接口,然後向服務端提供自己的唯一標識和其對應的 Binder 對象。服務端只需要一個 Service,服務器提供一個 queryBinder 接口,它會根據業務模塊的特徵來返回相應的 Binder 對象,不同的業務模塊拿到所需的 Binder 對象後就可進行遠程方法的調用了

更多完整項目下載。未完待續。源碼。圖文知識後續上傳github。
可以點擊關於我聯繫我獲取
https://github.com/xiangjiana/Android-MS

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章