一次 ContentObserver onChange 未被调用的问题分析

一、问题:
在 android6.0 上使用 ContentObserver 监听 Settings 数据库某个字段变化时,出现了 onChange 方法没有回调的问题。当时部分代码如下:
    private final class SettingsObserver extends ContentObserver {
        public ShutdownSettingsObserver(Handler handler) {
            super(handler);
        }

        @Override
        public void onChange(boolean selfChange, Uri uri) {
            Log.d(TAG, "onChange uri = " + uri);
        }
    }
    
    private Handler mHandler = new Handler() {
        @Override
        public void dispatchMessage(Message msg) {
            int what = msg.what;
            Log.d(TAG, "what = " + what);
        }
    };
    
    mSettingsObserver = new SettingsObserver(mHandler);
    
    mResolver.registerContentObserver(mSettingsUri,
                false, mSettingsObserver);
                

打印 log 发现,每次数据库字段变化时,都会打印而 onChange 不会被执行:
12-13 08:39:18.947 D/SettingsObserver( 2527): what = 0

二、修改问题:
修改为如下即可,使用 null 而不使用已有的 hander。
private final class SettingsObserver extends ContentObserver {
        public ShutdownSettingsObserver() {
            super(null);
        }

        @Override
        public void onChange(boolean selfChange, Uri uri) {
            Log.d(TAG, "onChange uri = " + uri);
        }
    }

三、问题原因:
查看 ContentObserver.java 源码发现,在如下方法中:
    private void dispatchChange(boolean selfChange, Uri uri, int userId) {
        if (mHandler == null) {
            onChange(selfChange, uri, userId);
        } else {
            mHandler.post(new NotificationRunnable(selfChange, uri, userId));
        }
    }
当 mHandler 为空时,直接调用了 onChange 方法。
当 mHandler 不为空时,会通过 mHandler post 一个 what=0 的消息,在 NotificationRunnable 中执行 onChange 方法。
而在我实现的源码中,重新实现了 mHandler dispatchMessage 方法,没有执行默认 what=0 的消息,所以 onChange 一直没有被调用。
    
    

你可能感兴趣的:(Android)