(二)如何保证应用永不崩溃

不啰嗦直接上代码,你们请看

public class CrashHandlerManager {
    private static CrashHandlerManager instance;
    private static Context mContext;
    private CrashHandlerManager(){}

    public static CrashHandlerManager getInstance(Context context){
        if(instance==null){
            mContext=context.getApplicationContext();
            instance=new CrashHandlerManager();
        }
        return  instance;
    }
    public void init(){
        Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler(){
            @Override
            public void uncaughtException(Thread t, Throwable e) {
                handleException(e);
                //判断当前线程是不是主线程
                if(t== Looper.getMainLooper().getThread()){
                    handleMainThread(e);
                }
            }
        });
    }

    private void handleMainThread(Throwable e) {
        while (true) {
            try {
                Looper.loop();
            } catch (Throwable throwable) {
                handleException(throwable);
            }
        }
    }

    private void handleException(Throwable e) {
        //写入错误日志
        //上传日志
    }
}

复制代码

你们很容易就看懂了这个类,保证应用永不崩溃关键在于handleMainThread这个方法。一旦主线程中出现异常就会致使Looper.loop没法正常轮询,看过源码的都知道Looper.loop是执行在ActivityThread的main方法中,只会执行一次,而Looper.loop不能正常轮询就会致使应用崩溃。其中利用Looper.loop是一个阻塞方法的特性,咱们能够给它外面套上一层无限循环,一旦出错就会从新启动轮询。bash

若是想了解Thread.setDefaultUncaughtExceptionHandler为何能够阻止应用crash,能够查看前一篇文章markdown

经过Thread.setDefaultUncaughtExceptionHandler阻止程序崩溃的源码解析ide

最后关于handleException的处理

因为各个公司对错误信息处理级别不一样,针对错误数据的封装也会各不同,我只是提一点我的小建议和心得。oop

1.把错误信息作相应的拆分和拼装,生成规定格式的错误数据,写入日志文件,日志文件能够是区间日志也能够是即刻日志(由于错误信息要分等级,若是是重大bug须要及时上传,并经过短信和邮件及时通知开发人员)post

2.存储当前设备信息(用户,厂商,系统,版本)到错误日志性能

3.既然本地有错误日志确定要上传,不过上传的间隔确定要控制,毕竟上传耗费性能(看大家后台须要刷新错误日志的间隔,)spa

4.上传完成记得及时清除线程

5.后台构建错误监控模块(不单单针对应用的bug也有多是部分接口功能异常等),针对重大bug,对应用bug功能及时进行动态屏蔽(对应用内部的功能作接口控制),而后用热修复或者应用更新解决问题。日志