1. 程式人生 > >android.os.TransactionTooLargeException異常

android.os.TransactionTooLargeException異常

http://blog.csdn.net/ballonge/article/details/51085778

一. 背景

輸入法在V2.30(185)和V2.35(196)兩個版本中都碰到了大量的TransactionTooLargeException的崩潰問題,其中崩潰的堆疊有所不同:

  • V2.30:android.app.ApplicationPackageManager.getInstalledPackages(ApplicationPackageManager.java:464)
  • V2.35:android.view.inputmethod.InputMethodManager.getEnabledInputMethodList(InputMethodManager.
    java:602
    )
最終通過查詢程式碼中的改動點,發現其中的原因就是:多個執行緒同時呼叫了以下的介面:
  • List<RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses();
  • List<RunningTaskInfo> tasksInfo = activityManager.getRunningTasks(1);
  • List<PackageInfo> appInfoList = pkgManager.getInstalledPackages(0);  
那麼為什麼呼叫這些介面會出現這個異常呢,我們從異常出現的原因為出發點進行講解。 二. TransactionTooLargeException的原因
     因為Binder太大了導致傳輸失敗。      當呼叫遠端(跨程序)方法時,方法所帶的引數以及返回值多會以parcel物件儲存在Binder傳輸緩衝區進行傳輸的。如果引數或者返回值所佔的記憶體超過傳輸緩衝區,呼叫將會失敗同時會丟擲TransactionTooLargeException異常。      Binder傳輸緩衝區是同一程序中所有傳輸操作所共享的,大小為1Mb。因此當程序中同一時刻,如果有大量的跨程序方法呼叫時,就要注意了。 從以上異常的描述,可以總結出現該異常的原因:
  • 跨程序方法呼叫
  • 呼叫的方法帶的引數或者返回值佔用較多記憶體
  • 同一時刻方法呼叫次數太多

三. 輸入法為何出現TransactionTooLargeException
 從TransactionTooLargeException出現的原因可知:
  • 跨程序方法呼叫
     檢視android的框架原理機制瞭解android的框架機制是通過IPC的機制去實現各個服務的管理,所有服務管理物件都是跨程序的呼叫,如:      PackageManager,InputMethodManager,ActivityManager都是通過binder傳輸進行跨程序呼叫
  • 呼叫的方法帶的引數或者返回值佔用較多記憶體
 獲取使用者所有安裝應用列表,如果使用者安裝大量應用的情況下,資料量還是比較大
  • 同一時刻方法呼叫次數太多
     輸入法啟動時會呼叫2次getInstalledPackages,廣告sdk智慧預載入每隔10s會呼叫一次getRunningAppProcesses或者getRunningTasks,呼叫5-6次getInstalledPackages 四. 如何避免    瞭解問題出現的條件後,該問題就迎刃而解,同時在專案開發過程中就需要避免問題的發生,整理的方法如下:
  •   跨程序方法呼叫時儘量減少引數或者返回值的記憶體佔用
          如:getInstalledPackages使用過濾引數減少返回結果的記憶體佔用
  •  不要多個執行緒同時呼叫跨程序方法,儘量減少呼叫次數或者重複利用呼叫的結果 
          如: 整個專案中共用一份安裝列表,減少getInstalledPackages的呼叫次數; 如果同一時刻需要呼叫getInstalledPackages,getRunningAppProcesses,getRunningTasks等方法,請使用同一個執行緒進行操作