【问题标题】:How can I update my local SQLite database whenever there is any update in my Contacts每当我的联系人中有任何更新时,如何更新我的本地 SQLite 数据库
【发布时间】:2016-04-07 05:30:39
【问题描述】:

我正在创建一个 Android 应用程序,其中有一个本地 SQLite 数据库来存储从联系人列表中选择的用户详细信息。每当我的手机联系人中有任何更新时,我都希望更新我的 SQLite 数据库。我使用了 Content Observer,但由于我是 Android 开发的新手,任何人都可以帮助我使用 ContentObserver 以及我可以遵循的方法来更新我的本地数据库。

【问题讨论】:

  • 您可以使用服务定期检查联系人是否有变化并更新您的数据库..

标签: android sqlite contentobserver


【解决方案1】:

ContentObserver 是一个没有抽象方法的抽象类。它的两个 onChange() 方法是在没有任何逻辑的情况下实现的。而且由于每当发生更改时都会调用它们,因此您必须覆盖它们。

由于 Google 在 API 级别 16 中添加了两个重载的 onChange() 方法之一,因此该方法的默认行为是调用另一个较旧的方法。

下面是正常实现的样子:

class MyObserver extends ContentObserver {
 public MyObserver(Handler handler) {
  super(handler);
}

 @Override
 public void onChange(boolean selfChange) {
  this.onChange(selfChange, null);
 }      

  @Override
  public void onChange(boolean selfChange, Uri uri) {
  // do s.th.
  // depending on the handler you might be on the UI
  // thread, so be cautious!
 }
}

上面的代码有些事情很重要。您必须知道的第一件事是,第二种方法只能从 API 级别 16 开始使用。这就是我添加 SuppressLint 注释的原因。该代码在旧设备上运行良好,但在这种情况下,Android 显然总是调用旧设备。因此,您的代码不应依赖 URI 才能正常工作。

还要注意构造函数中的 Handler 参数。此处理程序用于传递 onChange() 方法。所以如果你在 UI 线程上创建了 Handler,onChange() 方法也会在 UI 线程上被调用。在这种情况下,请避免在此方法中查询 ContentProvider。而是使用 AsyncTask 或 Loader。

如果您将空值传递给构造函数,Android 会立即调用 onChange() 方法——无论当前使用的线程如何。我认为在创建 ContentObserver 对象时最好始终使用处理程序。

注册您的内容观察者以监听变化

要注册您的 ContentObserver 子类,您只需调用 ContentResolver 的 registerContentObserver() 方法:

getContentResolver().registerContentObserver(SOME_URI,true,yourObserver);

它需要三个参数。第一个是要监听的 URI。我将在下一节中更详细地介绍 URI。

第二个参数指示对以给定 URI 开头的 URI 的所有更改是否应触发方法调用,或者仅更改为仅此一个 URI。这对于说带有许多后代的 ContactsContract URI 来说很方便。但它也可能是有害的,因为导致方法调用的实际更改对您来说更加模糊。

第三个参数是您的 ContentObserver 实现的实例。

你可以观察到的 URIs

正如我对内容提供者的介绍中所述,内容 URI 可以是基于目录或基于 id 的。

这两种 URI 类型都可以用于您的内容观察者。如果您有一个详细信息屏幕,您将为您的观察者使用基于 id 的 URI,而当您使用数据列表时,基于目录的 URI 更合适。

但这并不总是有效。例如,ContactsContract 总是会触发更改,无论何时更改任何联系人,即使您正在侦听更具体的 URI。这取决于内容提供者的正确实现。我已经为 ContactsContract 提供者提交了错误报告。如果您同意,请为这个问题投票。

当您为应用编写内容提供程序时,请注意通知正确的 URI。仅当您这样做时,此处描述的反馈机制才有效。这对您的观察者很重要——或者如果提供者也为您客户的观察者导出。这对装载机也很重要。请参阅我的帖子,了解如何编写内容提供程序以了解更多信息。

注意:如果您使用 Loaders,您不需要自己监听更改。在这种情况下,Android 会注册一个 ContentObserver 并触发您的 LoaderCallbacks onLoadFinished() 方法进行任何更改。

不要忘记注销您的内容观察者

注册内容观察者后,您也有责任取消注册。否则你会造成内存泄漏,你的 Activity 永远不会被垃圾回收。

要取消注册,请调用 ContentResolver 的 unregisterContentObserver() 方法:

getContentResolver().
  unregisterContentObserver(yourObserver);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多