Android运行时异常处理(防crash)

作者: ccDown | 来源:发表于2019-04-15 17:53 被阅读168次

    什么,软件又崩溃了。。。。。。。
    在这个时候总是很气愤,作为一个软件为什么你不能自己处理bug。那我们能不能让崩溃的地方可控也就是防止软件crash,就显得水平不那么菜了。。。hiahiahia。那就来吧。

    要做到防crash首先要捕获系统抛出的不能处理的异常,把异常像JavaIO抛出的IO异常一样自己消化掉,然后让Looper继续looper()拿到接下来的message,整个Handler机制又开始转起来了。。。也就是成为了一个不会crash的软件了

    (什么,这就完了?这不就是把线程的异常都捕获了集中处理么。。。)


    第一步 :捕获异常

    1.自定义一个Thread.UncaughtExceptionHandler类
    2.调用Thread.setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh)方法,使异常信息回调到自定义的uncaughtException中;
    3.在自定义的uncaughtException方法中处理异常,如上传日志、保存为文件等。

    1.自定义Thread.UncaughtExceptionHandler类

    class CrashHandler implements Thread.UncaughtExceptionHandler {
    @Override
    public void uncaughtException(Thread t, final Throwable e) {
      }
    }
    

    2.设置异常处理

    public void initHandler(final UncaughtExceptionCallBack uncaughtExceptionCallBack) {
        Thread.setDefaultUncaughtExceptionHandler(this);
    }
    

    3.异常回调处理信息

    @Override
    public void uncaughtException(Thread t, final Throwable e) {
        Log.e("CrashHandler  ", "偶吼吼,抓到错误信息了" + t.getName() + e.toString());
    }
    

    4.在Application的onCreate方法中调用initHandler方法就OK了


    第二步:上边完成了基本的运行时异常回调处理,下面进行如何防止应用因为运行时异常崩溃

    GitHub上大佬的思路是将Looper进行异常捕获,然后进行异常分发,把这个异常消费掉以后接着从MessageQueue中取下一个Message进行处理,那我们的过程就有了。

    1.捕获异常
    2.回调出去并进行相应的处理

    代码实现思路:创建一个自定义的Thread.UncaughtExceptionHandler类,在Application中进行初始化事件的分发。

    1.创建类

    class CrashHandler implements Thread.UncaughtExceptionHandler{
    
    /**自定义的异常处理回调*/
    private UncaughtExceptionCallBack uncaughtExceptionCallBack;
    
    public interface UncaughtExceptionCallBack{
        void caughtUncaughtException(Thread t,Throwable e);
    }
    
    private static CrashHandler crashHandler;
    
    public static synchronized CrashHandler getInstance(){
        if (crashHandler == null){
            synchronized (CrashHandler.class){
                if (crashHandler == null) {
                    crashHandler = new CrashHandler();
                }
            }
        }
        return crashHandler;
    }
    
    /**
     * 设置自定义的运行时异常处理
     * @param uncaughtExceptionCallBack
     */
    public void initHandler(final UncaughtExceptionCallBack uncaughtExceptionCallBack){
        this.uncaughtExceptionCallBack = uncaughtExceptionCallBack;
    
        Thread.setDefaultUncaughtExceptionHandler(this);
         /**
         * 为什么要通过new Handler.post方式而不是直接在主线程中任意位置执行 
         * while (true) { 
         *      try { 
         *          Looper.loop(); 
         *      } catch (Throwable e) {
         *      } 
         *  }
         *
         * 这是因为该方法是个死循环,若在主线程中,比如在Activity的onCreate中执行时
         * 会导致while后面的代码得不到执行,activity的生命周期也就不能完整执行,
         * 通过Handler.post方式可以保证不影响该条消息中后面的逻辑。
         *
         * 摘抄自:https://github.com/android-notes/Cockroach/blob/master/%E5%8E%9F%E7%90%86%E5%88%86%E6%9E%90.md
         */
        new Handler(Looper.getMainLooper()).post(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        Looper.loop();
                    } catch (Throwable e) {
                        if (uncaughtExceptionCallBack != null) {
                            uncaughtExceptionCallBack.caughtUncaughtException(Looper.getMainLooper().getThread(), e);
                        }
                    }
                }
            }
        });
    }
    
    @Override
    public void uncaughtException(Thread t, final Throwable e) {
        if (uncaughtExceptionCallBack != null) {
            uncaughtExceptionCallBack.caughtUncaughtException(Looper.getMainLooper().getThread(), e);
        }
    }
    }
    

    2.Application中初始化事件

    public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
    
        CrashHandler.getInstance().initHandler(new CrashHandler.UncaughtExceptionCallBack() {
            @Override
            public void caughtUncaughtException(Thread t, Throwable e) {
                Log.e("CrashHandler  ","偶吼吼,抓到错误信息了"+t.getName()+e.toString());
            }
        });
    }
    }
    

    就酱,我们的软件长大一点点了,可以自己跟系统抢异常了。。。(还是增长自己的代码姿势才是王道)
    整个流程仿照的GitHub一个封装好的Cockroach框架1.0版本,仰望大佬,大佬链接奉上:https://github.com/android-notes/Cockroach

    相关文章

      网友评论

        本文标题:Android运行时异常处理(防crash)

        本文链接:https://www.haomeiwen.com/subject/kahpwqtx.html