android子线程不处理异常导致崩溃

1.android在子线程不处理异常,导致程序崩溃

java在子线程不处理异常,main线程还会继续执行;android在子线程不处理异常,会导致crash,进程会被杀死。
android子线程不处理异常导致崩溃_第1张图片我在对android媒体库执行删除操作的时候,写法有问题,所以报了参数非法异常。
错误写法:

public void deleteMediaItem(MediaInfo mediaInfo) {
    String where = MediaStore.MediaColumns.DATA + " = " + mediaInfo.getPath();
    int recordRowsDeleted = mContentResolver.delete(FILE_URI, where, null);
    LogUtils.d(TAG + " media recordRowsDeleted:" + recordRowsDeleted);
}

正确写法:

public void deleteMediaItem(MediaInfo mediaInfo) {
    LogUtils.i(TAG + "deleteMediaItem: mediaInfo = " + mediaInfo);
    String where = MediaStore.MediaColumns.DATA + "=?";
    String[] selectionArgs = new String[]{mediaInfo.getPath()};
    int recordRowsDeleted = mContentResolver.delete(FILE_URI, where, selectionArgs);
    LogUtils.d(TAG + " media recordRowsDeleted:" + recordRowsDeleted);
}

在子线程中没有显式地处理异常
错误写法:

RxUtils.requestData(Observable.create(emitter -> {
    for (RecordVideo recordVideo : recordVideoList) {
        MediaInfo mediaInfo = mDataBaseManager.convertRecordToMediaInfo(recordVideo);
             if (recordVideo.getR() != 1) {
                  mDataBaseManager.insertMediaItem(mediaInfo);
             } else if (recordVideo.getR() == 1) {
                  mDataBaseManager.deleteMediaItem(mediaInfo);
             }
    	}
    	emitter.onNext(0);
    }), o -> {
        LogUtils.d(TAG + "value:" + o);
    });                    

正确写法:

RxUtils.requestData(Observable.create(emitter -> {
                        try {
                            List<MediaInfo> mediaInfoList = new ArrayList<>();
                            for (RecordVideo recordVideo : recordVideoList) {
                                MediaInfo mediaInfo = mDataBaseManager.convertRecordToMediaInfo(recordVideo);
                                if (recordVideo.getR() != 1) {
                                    mediaInfoList.add(mediaInfo);
                                    if (mediaInfoList.size() == Constants.GALLERY_NETWORK_SIZE_SMALL) {
                                        int insertRows = mDataBaseManager.bulkInsertMediaItem(mediaInfoList);
                                        LogUtils.d(TAG + "bulkInsert rows" + insertRows);
                                        mediaInfoList.clear();
                                    }
                                } else if (recordVideo.getR() == 1) {
                                    mDataBaseManager.deleteMediaItem(mediaInfo);
                                }
                            }
                            if (mediaInfoList.size() > 0) {
                                int insertRows = mDataBaseManager.bulkInsertMediaItem(mediaInfoList);
                                LogUtils.d(TAG + "loadRecordVideos bulkInsert rows" + insertRows);
                                mediaInfoList.clear();
                            }
                            emitter.onNext(0);
                        } catch (Exception e) {
                            emitter.onError(e);
                        }
                    }), result -> {
                        LogUtils.d(TAG + "loadRecordVideos delete result:" + result);
                    }, error -> {
                        LogUtils.d(TAG + "loadRecordVideos delete error" + error);
                    });

2.为什么?

java中子线程不处理异常,main线程还会继续执行;android中子线程不处理异常,程序却会崩溃。
重点:Android和Java的默认UncaughtExceptionHandler
在java中:

public static void main(String[] args) {
        Thread.UncaughtExceptionHandler uncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
        System.out.println("Java getDefaultUncaughtExceptionHandler:" + uncaughtExceptionHandler);
    }
Java getDefaultUncaughtExceptionHandler:null

在android中:

public void getDefaultUncaughtExceptionHandler(View view) {
        Thread.UncaughtExceptionHandler uncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
        Log.d("top huang", "Android getDefaultUncaughtExceptionHandler:" + uncaughtExceptionHandler);
    }
Android getDefaultUncaughtExceptionHandler:com.android.internal.os.RuntimeInit$KillApplicationHandler@45c74

得出结论:java中没有默认的UncaughtExceptionHandler,android中有一个UncaughtExceptionHandler (RuntimeInit$KillApplicationHandler)

3.查看android中UncaughtExceptionHandler的源码

public class RuntimeInit {
    ...
    /**
     * Logs a message when a thread encounters an uncaught exception. By
     * default, {@link KillApplicationHandler} will terminate this process later,
     * but apps can override that behavior.
     */
    private static class LoggingHandler implements Thread.UncaughtExceptionHandler {
        public volatile boolean mTriggered = false;

        @Override
        public void uncaughtException(Thread t, Throwable e) {
            //...打印log信息...
            }
        }
    }

    /**
     * Handle application death from an uncaught exception.  The framework
     * catches these for the main threads, so this should only matter for
     * threads created by applications. Before this method runs, the given
     * instance of {@link LoggingHandler} should already have logged details
     * (and if not it is run first).
     */
    private static class KillApplicationHandler implements Thread.UncaughtExceptionHandler {
        private final LoggingHandler mLoggingHandler;

        /**
         * Create a new KillApplicationHandler that follows the given LoggingHandler.
         * If {@link #uncaughtException(Thread, Throwable) uncaughtException} is called
         * on the created instance without {@code loggingHandler} having been triggered,
         * {@link LoggingHandler#uncaughtException(Thread, Throwable)
         * loggingHandler.uncaughtException} will be called first.
         *
         * @param loggingHandler the {@link LoggingHandler} expected to have run before
         *     this instance's {@link #uncaughtException(Thread, Throwable) uncaughtException}
         *     is being called.
         */
        public KillApplicationHandler(LoggingHandler loggingHandler) {
            this.mLoggingHandler = Objects.requireNonNull(loggingHandler);
        }

        @Override
        public void uncaughtException(Thread t, Throwable e) {
            try {
                ensureLogging(t, e); //打印log
                ...
            } catch (Throwable t2) {
                ...
            } finally {
                // Try everything to make sure this process goes away.
                Process.killProcess(Process.myPid());  // 杀死当前进程
                System.exit(10);
            }
        }
        ......
    }
}

一般有三种UncaughtExceptionHandler:

UncaughtExceptionHandler种类 优先级
线程私有的UncaughtExceptionHandler 最高
ThreadGroup的UncaughtExceptionHandler 其次
静态默认的UncaughtExceptionHandler 最后

我们没有人为地处理异常,就会交给KillApplicationHandler进行处理,这样的话就会打印对应的异常日志,并且将该进程杀死。

4.总结

  1. UncaughtExceptionHandler的获取顺序(当前线程–>ThreadGroup -->DefaultUncaughtExceptionHandler)
  2. 默认没有UncaughtExceptionHandler的时候,系统会打印出崩溃异常路径
  3. Java中子线程崩溃,main线程是不受影响,继续执行,直到休眠结束。
  4. Android是子线程崩溃后,整个进程都崩溃
  5. Java没有默认UncaughtExceptionHandler ,Android有默认的UncaughtExceptionHandler(RuntimeInit$KillApplicationHandler)
  6. Android是子线程崩溃后,整个进程都崩溃,崩溃原因是:KillApplicationHandler中kill掉了整个进程

你可能感兴趣的:(android开发,android,java)