Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/327.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在游标发生1次更改后调用了两次Content Observer onChange方法_Java_Android_Android Contentprovider - Fatal编程技术网

Java 在游标发生1次更改后调用了两次Content Observer onChange方法

Java 在游标发生1次更改后调用了两次Content Observer onChange方法,java,android,android-contentprovider,Java,Android,Android Contentprovider,我有一个应用程序,我希望将android联系人列表中的详细信息发送到远程服务器,这样用户就可以在线查看他的联系人。 为此,我想通知远程服务器在手机上对联系人列表所做的任何更改 我已经在“Contacts contract.Contacts.CONTENT\u URI”上设置了ContentObserver,该服务在手机启动时启动 我有几次安静,前两次是偶然的,第三次是我最担心的 1:一旦我设置了一个在我的游标上注册ContentObserver的服务,该观察者是否只存在于该服务中?我的意思是,如

我有一个应用程序,我希望将android联系人列表中的详细信息发送到远程服务器,这样用户就可以在线查看他的联系人。 为此,我想通知远程服务器在手机上对联系人列表所做的任何更改

我已经在“Contacts contract.Contacts.CONTENT\u URI”上设置了ContentObserver,该服务在手机启动时启动

我有几次安静,前两次是偶然的,第三次是我最担心的

1:一旦我设置了一个在我的游标上注册ContentObserver的服务,该观察者是否只存在于该服务中?我的意思是,如果服务被终止,contentObserver会继续观察吗

2:我想答案是否定的,但我还是会问。有没有办法知道更新的联系人触发了我的contentObserver的onchange方法?目前,我必须编辑手机上所有联系人的列表,并将其发送到我的远程服务器,只需发送正在更新的联系人的详细信息就可以轻松得多

3:这是我的主要问题,当我更改联系人列表时,onChange方法会连续两次被触发。1个零钱,2个电话。有没有办法管理这件事

    public class ContactService extends Service {

    JSONArray contactList;

    @Override
    public IBinder onBind(Intent arg0) {
        return null;
    }

    @Override
    public void onCreate() {
        Log.i("C2DM","content observers initialised");
        super.onCreate();



        //Call Log Content Provider observer

        MyContentContactsObserver contactsObserver = new MyContentContactsObserver();
        ContactService.this.getContentResolver().registerContentObserver (ContactsContract.Contacts.CONTENT_URI, true, contactsObserver);   

    }

    private class MyContentContactsObserver extends ContentObserver {

        public MyContentContactsObserver() {
            super(null);
        }

        @Override
        public void onChange(boolean selfChange) {
            super.onChange(selfChange);    
            Log.i("LOG","detected change in contacts: "+selfChange);
        }
    }
}
结果在我的logCat中有两条快速行:

 detected change in contacts: false 
 detected change in contacts: false

我做了一个类似的实现,并在日历的事件
URI
上设置了
ContentObserver
。我面对了你现在面临的所有问题。所以你的问题和我的解决方案/建议都在这里

1) 一旦我建立了一个在上注册ContentObserver的服务 我的光标, 该观察者是否仅存在于服务中?我是说,如果服务被杀了, 内容观察者是否继续观察

不,它不会通过URI观察您的内容。但这是有解决办法的。您可以创建一个始终运行的服务。由于内存问题或其他意外取消,此服务一被取消,将立即重新创建。它将始终继续运行,除非明确取消它。要在服务类中创建这样的服务覆盖
onstart命令(Intent-Intent,int-flags,final-int-startId)
,请返回
START\u-STICKY
。看看下面的代码

public int onStartCommand(Intent intent, int flags, final int startId) {

    String authenticationKey = ((MainApplication) getApplicationContext()).getDbConnector().getUserAuthDefault() ;
    // if user is not registered yet, stop this service, it may be called from boot reciever.
    if(authenticationKey == null){
        stopSelf();
    }

    // restart, if we get killed.
    return START_STICKY;
}  

2:我想答案是否定的,但我还是会问。还有吗 知道哪一个 正在更新的联系人正在触发我的contentObserver的onchange方法? 目前,我必须整理所有电话联系人的名单,并将其发送给 在我的远程服务器上,只发送正在更新的联系人的详细信息会容易得多

你又猜对了。答案是否定的。
无法具体知道哪个联系人已更新。ContentObserver只提供一个事件,让您知道uri所指向的数据已经发生了一些更改。但我认为您处理这种情况的效率很低,因为您正在编译所有联系人的列表并将其发送回服务器。
我建议您在本地存储中维护一个联系人列表,这些联系人已成功发送到服务器。下次当您在
contentObserver
onChange()
方法中接到呼叫时,您将从
content\u URI
获取所有
联系人,将其与以前存储的列表进行比较,并仅将更新的联系人发送到服务器

3:这是我的主要问题,当我更改联系人列表时 onChange方法 很快就被解雇了两次。1个零钱,2个电话。有管理的方法吗 这个

是的,这种情况会发生,但我想你的印象是错误的。在我的例子中,它曾经随机发射两到三次甚至更多次。所以我设定了一个时间间隔的阈值。如果再次触发
ContentObserver
,则我不会处理它的时间间隔。我做了这样的事

long lastTimeofCall = 0L;
long lastTimeofUpdate = 0L;
long threshold_time = 10000;

    /* (non-Javadoc)
     * @see android.database.ContentObserver#onChange(boolean)
     */
    @Override
    public void onChange(boolean selfChange) {
        super.onChange(selfChange);

        Log.d("content service", "on change called");

        lastTimeofCall = System.currentTimeMillis();

        if(lastTimeofCall - lastTimeofUpdate > threshold_time){

         //write your code to find updated contacts here

          lastTimeofUpdate = System.currentTimeMillis();
        }

    }  

希望这些建议/解决方案能有所帮助。

考虑如何注册观察员。
registerContentObserver
的第二个参数是
boolean notifyForDescendents
,您已将其设置为
true
。因此,当ContactsContract.Contacts.CONTENT\u URI或其任何描述标准URI发生更改时,您将收到通知。可能是对具有给定id的联系人的某些操作会触发特定联系人uri和全局联系人uri的通知,第二个参数为
true
您的观察者会同时观察到这两个参数

另一件事是,您可以为特定联系人id uri注册content observer-
ContentURI.withAppendedId(ContactsContract.Contacts.content\u uri,contactId)
。然而,这与您的问题无关,但为每个联系人注册单独的观察者看起来相当难看;)

另一个建议是:可能将observer保留为最终字段,而不是在onCreate中重新创建它(但只在那里注册它)


直接到你的3号:两次给你的观察者打电话之间有多长时间?我想你的观察者会因为联系人同步而被呼叫两次,这也会更新数据库。第一次是您的实际更新,第二次是同步完成并在同一联系人行中注册其同步值时


您能关闭同步并查看它是否仍然被调用两次吗?

在我自己的代码中遇到了同样的问题,并发现我调用了registerContentObserver()两次。尽管它是针对完全相同的URI并且在同一个类中,但我的onChange(布尔自更改)方法被调用了两次。

您可能有两个或多个ContactService实例,它们都注册为相同的ContactsContacts.Contacts.CONTENT\u URI。

+1,10000ms秒在所有情况下都能正常工作吗,你有没有从用户那里得到任何反馈,谢谢?我还没有从用户那里得到任何反馈。
public class ContactService extends Service {

    private final ContentObserver contactsObserver = new ContentObserver(null) {

        @Override
        public void onChange(boolean selfChange) {
            super.onChange(selfChange);    
            Log.i("LOG","detected change in contacts: "+selfChange);

            //your code here
        }
    };

    @Override
    public IBinder onBind(Intent arg0) {
        return null;
    }

    @Override
    public void onCreate() {

        super.onCreate();

        getContentResolver().registerContentObserver(
                ContactsContract.Contacts.CONTENT_URI, true, contactsObserver);   
    }

    @Override
    public void onDestroy() {

        getContentResolver().unregisterContentObserver(contactsObserver);

        super.onDestroy();
    }
}