关于 contentObserver()中的onChang()执行两次的问题

本文介绍了一种通过监听数据库变化来实现短信监听的方法,并提供了一个简单的示例代码,该方法能够有效避免第三方应用拦截的问题。

计划是写一个监听信息的东西,在网上一查,好多大婶们都说如果监听广播的话很有可能被第三方的信息应用比如飞信或者GO短信把广播截取了,因为急着做出东西,就没采取这条路,有机会试试监听广播的方法,看看是否可行,毕竟自己看到了才确定嘛!鼓励动手,坚持执行力~~

 我采用的是监听数据库变化的方法来监听信息,监听数据库的话就用到了本文的主角了ContentObserver(handler),当然它对我们有用的就是onChange()方法了,但是经过调试,发现每次接收到信息这个onChange()方法都会执行两次,这样对要执行的动作就会有影响,然后网上找了找貌似有很多人碰到这个问题,但都没有解决方法,目前还没找到方法,会继续寻找,哪位有办法可以告诉我一声。

虽然没有从原理上解决这个问题的办法,但我们可以灵活的绕过这个问题最后达到我们要的效果:

上一段代码 大家看看 欢迎拍砖交流

private final ContentObserver simChangeObserver =
       new ContentObserver(new Handler()) {
   @Override
   public void onChange(boolean selfUpdate) {
       super.onChange(selfUpdate);
       startQuery();
     if(!isQuery){
    	 showMessage();
     }else{
    	 //do nothing
     }
   }
};

 private void startQuery() {
        try {
           //mQueryHandler.startQuery(0, null, ICC_URI, null, null, null, null);
        	 mCursor = managedQuery(Uri.parse("content://sms/"), 
        			 null, 
        			 null, 
        			 null,
        			 null); 
        } catch (SQLiteException e) {
            //
        }
        
        j++;
       if(j%2 == 0){
        isQuery = true;
        }
    }

呃 算是比较取巧的办法~~

### 三级标题:Android 中多次调用 registerContentObserver 的影响 在 Android 中,多次调用 `ContentResolver.registerContentObserver` 方法会对系统资源和应用性能产生一定影响。具体来说,每次调用 `registerContentObserver` 都会向 `ContentResolver` 注册一个新的 `ContentObserver` 实例,这些实例会被存储在一个内部列表中,用于监听特定 URI 的数据变化。如果多次注册相同的观察者或监听相同的 URI,可能导致以下问题: #### 1. 内存占用增加 每次注册都会创建一个新的 `ContentObserver` 实例,并将其存储在 `ContentResolver` 的观察者列表中。即使这些观察者没有被使用,它们仍然会占用内存,导致内存消耗增加。特别是当注册的观察者持有外部类(如 `Activity` 或 `Service`)的引用时,容易引发内存泄漏问题[^1]。 #### 2. 性能下降 由于每个注册的 `ContentObserver` 都会在数据变化时被通知,因此注册的观察者越多,`ContentResolver` 在调用 `notifyChange` 时需要遍历和执行的回调就越多,从而导致性能下降。这种影响在频繁触发数据变化的场景下尤为明显,例如监听媒体库变化的 `ContentObserver`。 #### 3. 重复监听与逻辑冲突 如果多次注册了监听相同 URI 的观察者,可能会导致多个 `onChange` 回调被同时触发,造成重复处理相同事件的情况。这不仅浪费了系统资源,还可能引发业务逻辑上的冲突。例如,如果多个观察者都尝试更新 UI,可能会导致界面状态不一致或异常刷新。 为了避免这些问题,建议在注册 `ContentObserver` 时进行去重管理。可以在注册前检查是否已经存在相同类型的观察者,或者使用一个统一的管理类来控制观察者的生命周期。例如: ```java public class ContentObserverManager { private ContentObserver observer; private final ContentResolver contentResolver; public ContentObserverManager(ContentResolver contentResolver) { this.contentResolver = contentResolver; } public void registerObserver(Uri uri, ContentObserver observer) { if (this.observer != null) { contentResolver.unregisterContentObserver(this.observer); } this.observer = observer; contentResolver.registerContentObserver(uri, true, this.observer); } public void unregisterObserver() { if (observer != null) { contentResolver.unregisterContentObserver(observer); observer = null; } } } ``` 通过这种方式,可以确保同一时间只有一个 `ContentObserver` 被注册,从而避免重复注册带来的性能问题和逻辑冲突。 此外,如果观察者是通过 `Cursor.setNotificationUri` 间接注册的,也需要关注其生命周期管理。该方法内部通过 `ContentResolver.registerContentObserver` 注册了一个内部类形式的 `ContentObserver`,并与 `Cursor` 实例绑定。若未正确管理 `Cursor` 生命周期,也可能导致观察者未被及时注销,进而影响系统资源使用。 ### 三级标题:如何避免多次注册 ContentObserver 为了有效避免多次注册 `ContentObserver`,可以采取以下措施: - **使用单例模式或管理类**:通过封装注册和注销逻辑,确保观察者只在需要时注册,并在不再需要时及时注销。 - **使用弱引用**:在观察者内部使用 `WeakReference` 持有外部对象(如 `Activity` 或 `Context`),防止因强引用导致的内存泄漏。 - **合理选择监听范围**:尽量避免监听全局 URI(如 `MediaStore.Images.Media.EXTERNAL_CONTENT_URI`),除非确实需要监听所有数据变化。否则,可以限定监听范围以减少不必要的通知。 ### 三级标题:总结 综上所述,多次调用 `registerContentObserver` 会导致内存占用增加、性能下降以及可能的逻辑冲突。为了避免这些问题,应在注册前进行检查,并确保在不再需要监听时及时注销观察者。通过合理的生命周期管理和资源回收机制,可以有效提升应用的稳定性和性能。 ---
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值