Android 中 降低 app crash 的方案。

代码实现

import android.app.Application
import android.content.Context
import android.os.Handler
import android.os.Looper
import android.util.Log
import java.lang.Exception

class MyApplication : Application() {
    
    
    override fun attachBaseContext(base: Context?) {
    
    
        super.attachBaseContext(base)
    }

    override fun onCreate() {
    
    
        super.onCreate()
        //避免 子线程中的异常 引起 crash
        Thread.setDefaultUncaughtExceptionHandler {
    
     t, e ->
            Log.d("xxx","thread::${
      
      t.name};;${
      
      e.message}")
            e.printStackTrace()
            errorHandler()
        }
        // 避免 主线程中异常 引起 crash
        Handler(Looper.getMainLooper()).post {
    
    
            while (true) {
    
    
                try {
    
    
                    Looper.loop()
                } catch (e: Exception) {
    
    
                    Log.d("xxx","${
      
      e.message}")
                    e.printStackTrace()
                    
                    errorHandler()
                }
            }
        }
    }

    private fun  errorHandler(){
    
    
        //里面实现 异常的具体处理方式,比如 日志上传;error toast 提示,app重启
    }
}

Handler(Looper.getMainLooper()).post () 方案 原理

  • 在 Android 中 ActivityThread 的源码中的loop方法中分发 主线程的 队列消息 ,源代码如下
  for (;;) {
    
    
            Message msg = queue.next(); // might block
            if (msg == null) {
    
    
                // No message indicates that the message queue is quitting.
                return;
            }

     //  =======================  分割线 =============================
            // This must be in a local variable, in case a UI event sets the logger
            final Printer logging = me.mLogging;
            if (logging != null) {
    
    
                logging.println(">>>>> Dispatching to " + msg.target + " " +
                        msg.callback + ": " + msg.what);
            }
            // Make sure the observer won't change while processing a transaction.
            final Observer observer = sObserver;

            final long traceTag = me.mTraceTag;
            long slowDispatchThresholdMs = me.mSlowDispatchThresholdMs;
            long slowDeliveryThresholdMs = me.mSlowDeliveryThresholdMs;
            if (thresholdOverride > 0) {
    
    
                slowDispatchThresholdMs = thresholdOverride;
                slowDeliveryThresholdMs = thresholdOverride;
            }
            final boolean logSlowDelivery = (slowDeliveryThresholdMs > 0) && (msg.when > 0);
            final boolean logSlowDispatch = (slowDispatchThresholdMs > 0);

            final boolean needStartTime = logSlowDelivery || logSlowDispatch;
            final boolean needEndTime = logSlowDispatch;

            if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {
    
    
                Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
            }

            final long dispatchStart = needStartTime ? SystemClock.uptimeMillis() : 0;
            final long dispatchEnd;
            Object token = null;
            if (observer != null) {
    
    
                token = observer.messageDispatchStarting();
            }
            long origWorkSource = ThreadLocalWorkSource.setUid(msg.workSourceUid);
            try {
    
    
                msg.target.dispatchMessage(msg);
                if (observer != null) {
    
    
                    observer.messageDispatched(token, msg);
                }
                dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
            } catch (Exception exception) {
    
    
                if (observer != null) {
    
    
                    observer.dispatchingThrewException(token, msg, exception);
                }
                throw exception;
            } finally {
    
    
                ThreadLocalWorkSource.restore(origWorkSource);
                if (traceTag != 0) {
    
    
                    Trace.traceEnd(traceTag);
                }
            }
            if (logSlowDelivery) {
    
    
                if (slowDeliveryDetected) {
    
    
                    if ((dispatchStart - msg.when) <= 10) {
    
    
                        Slog.w(TAG, "Drained");
                        slowDeliveryDetected = false;
                    }
                } else {
    
    
                    if (showSlowLog(slowDeliveryThresholdMs, msg.when, dispatchStart, "delivery",
                            msg)) {
    
    
                        // Once we write a slow delivery log, suppress until the queue drains.
                        slowDeliveryDetected = true;
                    }
                }
            }
            if (logSlowDispatch) {
    
    
                showSlowLog(slowDispatchThresholdMs, dispatchStart, dispatchEnd, "dispatch", msg);
            }

            if (logging != null) {
    
    
                logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
            }

            // Make sure that during the course of dispatching the
            // identity of the thread wasn't corrupted.
            final long newIdent = Binder.clearCallingIdentity();
            if (ident != newIdent) {
    
    
                Log.wtf(TAG, "Thread identity changed from 0x"
                        + Long.toHexString(ident) + " to 0x"
                        + Long.toHexString(newIdent) + " while dispatching to "
                        + msg.target.getClass().getName() + " "
                        + msg.callback + " what=" + msg.what);
            }

            msg.recycleUnchecked();
        }
  • 我们现在的这种做法相当于 将 上述代码分割线一下的代码替换成了 post()函数闭包里面的代码,即:
 for (;;) {
    
    
            Message msg = queue.next(); // might block
            if (msg == null) {
    
    
                // No message indicates that the message queue is quitting.
                return;
            }
             while (true) {
    
    
                try {
    
    
                    Looper.loop()
                } catch (Exception e ) {
    
    
                    Log.d("xxx","${e.message}")
                    e.printStackTrace()
                    errorHandler()
                }
            }
}

猜你喜欢

转载自blog.csdn.net/genmenu/article/details/107322482