中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Android 應用中出現crash如何解決

發布時間:2020-12-29 13:54:43 來源:億速云 閱讀:604 作者:Leah 欄目:開發技術

今天就跟大家聊聊有關Android 應用中出現crash如何解決,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結了以下內容,希望大家根據這篇文章可以有所收獲。

android main入口的commonInit()方法內處,有這么一句話,

Thread.setDefaultUncaughtExceptionHandler(new KillApplicationHandler(loggingHandler));

如果沒有這句話,app就不會crash。不信,你往里面看,

public KillApplicationHandler(LoggingHandler loggingHandler) {
 @Override
 public void uncaughtException(Thread t, Throwable e) {
 //捕獲到異常
   try {
     ......
     //打印crash日志,展示崩潰彈窗等
     // Bring up crash dialog, wait for it to be dismissed
     ActivityManager.getService().handleApplicationCrash(
       mApplicationObject, new ApplicationErrorReport.ParcelableCrashInfo(e));
      } catch (Throwable t2) {
        .... 
      } finally {
        // Try everything to make sure this process goes away.
        Process.killProcess(Process.myPid());//殺死進程
        System.exit(10);
      }
    }
  }

當異常KillApplicationHandler捕獲到異常,進行完一系列處理(主要是打印crash日志,通知AMS展示crash彈窗等)后,最終會殺死進程,這樣你的app就崩潰了。

既然都崩潰了,自定義異常捕獲器來屏蔽crash真的可行嗎?

肯定有人會說,自定義一個異常捕獲器,來覆蓋掉系統的KillApplicationHandler,然后在捕獲到異常后,不殺進程,app就不會崩潰了,就像下面這樣,

class MainApplication : Application() {
  override fun onCreate() {
    super.onCreate()
    Thread.setDefaultUncaughtExceptionHandler { _, e ->
      //捕獲到異常,只打印日志,不殺進程
      Log.e("MainApplication", "${Thread.currentThread().name} 捕獲到異常:${e.message}")
    }
  }
}

這其實只是隔壁老王的思路,雖然確實防護住子線程的crash,但是當主線程出現異常時,app還是無法正常運行。這是因為,當UncaughtExceptionHandler捕獲到線程拋出異常的時候,線程在執行完uncaughtException()中的處理后,就無法繼續存活了。如果拋異常的線程是主線程,那就意味著主線程會死掉,這時你即便不殺進程,進程活著也沒有任何意義了,app還是會停止運行。

把android異常捕獲機制在梳理一下,熟悉的同學可以跳過,直接進入下一節。

  • Thread.setCaughtExceptionPreHandler()覆蓋所有線程,會在回調DefaultExceptionHandler之前調用;

  • Thread.setCaughtExceptionHandler()同樣回覆蓋所有線程,可以在應用層被重復調用,并且每一次調用后,都會覆蓋上一次設置的DefaultUncaughtExceptionHandler;

  • Thread.currentThread.setUncaughtExceptionHandler(),只可以覆蓋當前線程的異常。如果某個線程存在自定義的UncaughtExceptionHandler,回調時會忽略全局的DefaultUncaughtHandler。

既然話都說到這份上了,就請接下never crash大招吧。

要想不crash,只能讓線程不要拋出exception,唯此別無他法。如果我們能把一個線程的所有的操作都使用try-catch進行保護,理論上,就能做到app never crash。由于android基于Handler事件驅動的機制,可以在app啟動時,向主線程中的MessageQueue中提交一個死循環操作,在這個死循環中不斷去poll事件,并且將這個死循環進行try-catch,這樣所有主線程中的異常都會被catch住,從而app就再也不會發生crash。

private fun openCrashProtected() {
    Log.d(tag, "openCrashProtected")
    Handler(Looper.getMainLooper()).post {
      while (true) {
        try {
          Looper.loop()
          Log.d(tag, "main looper execute loop")
        } catch (e: Throwable) {
          //所有主線程中的異常都會被catch住,從而不會發生crash
          Log.e(tag, "catch exception: " + e.message)
        }
      }
    }
  }

有人可能要說了,你這樣catch住主線程的異常了,頁面可能要亂套哇。話雖如此,但你可以在catch中做業務保護呀。比如,我這里采取的做法是,關閉棧頂activity。 解決ActivityLifeCycle,維護一個Activity棧,

private fun registerLifeCycle() {
    registerActivityLifecycleCallbacks(object : ActivityLifecycleCallbacks {
      override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
        ActivityStack.Instance().push(activity)
      }

      override fun onActivityResumed(activity: Activity) {
      }

      override fun onActivityStarted(activity: Activity) {
      }

      override fun onActivityPaused(activity: Activity) {

      }

      override fun onActivityDestroyed(activity: Activity) {
        ActivityStack.Instance().pop(activity)
      }

      override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {

      }

      override fun onActivityStopped(activity: Activity) {
      }
    })
  }

然后當catch住異常時,

//主線程出現異常,關閉棧頂activity
ActivityStack.Instance().curr()?.finish()

看完上述內容,你們對Android 應用中出現crash如何解決有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注億速云行業資訊頻道,感謝大家的支持。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

富阳市| 武定县| 自治县| 会同县| 玉田县| 固始县| 揭东县| 海口市| 石渠县| 沾化县| 新宁县| 高唐县| 剑川县| 全南县| 巨鹿县| 嵩明县| 呼玛县| 株洲市| 金门县| 油尖旺区| 临桂县| 青浦区| 昌宁县| 承德县| 惠州市| 共和县| 宁城县| 铅山县| 涟源市| 自治县| 忻城县| 江永县| 张家港市| 南昌市| 乌海市| 陵川县| 武功县| 桃江县| 安庆市| 昌平区| 神农架林区|