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

什么,软件又崩溃了。。。。。。。
在这个时候总是很气愤,作为一个软件为什么你不能自己处理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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,843评论 6 502
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,538评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,187评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,264评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,289评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,231评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,116评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,945评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,367评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,581评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,754评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,458评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,068评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,692评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,842评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,797评论 2 369
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,654评论 2 354

推荐阅读更多精彩内容

  • 1 什么是Crash Crash,即闪退,多指在移动设备(如iOS、Android设备)中,在打开应用程序时出现的...
    天才木木阅读 55,766评论 37 281
  • 稳定性测试是保障客户端稳定性的一种手段,致力于提前发现问题,收集更多异常信息,复现线上闪退。当Android客户端...
    one_step123阅读 8,075评论 0 0
  • 针对于Android开发的小伙伴来说,对于Android Monitor的logcat再熟悉不过了,在这里我们可以...
    _曦语阅读 1,295评论 0 3
  • Android系统碎片化造成应用程序崩溃严重,在模拟器上运行良好的程序安装到某款手机上说不定就会出现崩溃的现象。而...
    YoungTa0阅读 17,888评论 5 20
  • (一) 当熊两岁的时候,它走出自己居住的山洞。 我已经成年啦,它想,是时候去看一看外面的世界。 于是它把墙上剩下的...
    KawakamiTomie阅读 391评论 0 0