android - 没有 Content Provider 的 CursorLoader 和 SQLite

Posted

技术标签:

【中文标题】android - 没有 Content Provider 的 CursorLoader 和 SQLite【英文标题】:android - CursorLoader & SQLite without Content Provider 【发布时间】:2012-10-03 21:03:30 【问题描述】:

我知道这已经讨论过了,但我想问一下目前的情况。我是否必须创建一个 ContentProvider 才能将 CursorLoader 与 sqlite 数据库结合使用?

我找到了

CursorLoader usage without ContentProvider

正如 Emmby 评论的那样,看起来正是我所希望的

用户应该知道一个限制,那就是它没有刷新数据更改的机制(正如加载程序应该做的那样)

所以提到了另一种解决方案

https://github.com/commonsguy/cwac-loaderex

再次指出一些缺点

但是,要利用自动重新查询,您需要为 UI 和更新使用相同的加载程序,从而限制了其对后台服务的可用性。

当然,在使用 LoaderManager 时,我们希望获得引入它的所有好处。所以我的问题是,是否有一种方法可以将 LoaderManager 与 sqlite 数据库结合使用,而无需实现内容提供程序,但仍具有它的所有好处。

谢谢

【问题讨论】:

【参考方案1】:

您在帖子中提到的两个实现都提供了CursorLoader 的所有好处除了能够在基础内容更改时接收通知。

我最近一直在研究这个问题,我可以自信地告诉你,android API 目前不提供仅使用原始 SQLiteDatabase 的方法(它仅提供 ContentResolver#notifyChange() 和 @987654326 @方法,用于通知在某个通知Uri下注册的所有Cursor)。

也就是说,您现在的选择是:

    自己实现一个观察者,它能够在内容更改时从SQLiteDatabase 接收通知,并且能够以某种方式将这些通知中继到应用程序中所有现有的Loaders。我写了一篇相当广泛的blog post,关于如何实现Loaders,如果你想接受这个挑战,它可能会派上用场。或者……

    使用 Mark Murphy 的 LoaderEx 库,并且只能使用他的库提供的 AsyncTask 操作来修改数据库。请注意,他的任务刷新Loader 的原因是因为它们在执行插入/更新/删除后立即在Loader 上调用onContentChanged,有效地告诉Loader 内容已更改并且应该刷新其数据。

    只需使用ContentProviderCursorLoader,您就可以使用ContentResolver#notifyChange() 方法通知CursorLoader 发生了内容更改。

我正在尝试找出一个更好的解决方案,如果我找到/实施一个解决方案,我会在以后报告,但现在必须这样做。

【讨论】:

太好了,感谢您的详细回复。考虑到这一点,我只是觉得我应该实现一个内容提供程序,即使对于我可能想要在显示器上列出的任何小型数据库来说,这似乎都是一种过度杀伤力。嗯... @dorjeduck 是的,我通常也是这样做的。我真的很想找到一种方法来做到这一点......我还没有完成这个:) 爱 androiddesignpatterns.com @dorjeduck 谢谢!在那之前,我会尝试写一些更酷的东西:P @AlexLockwood,这是否意味着为了以异步方式加载数据并获得我们需要的数据更改通知(这是推荐的方式?)首先实现 ContentProvider?我认为 ContentProviders 的目的是与其他应用程序共享数据,正如他们的描述所示,但看起来这不是唯一的目的。【参考方案2】:

这是我的解决方案,在我的 onCreateLoader 中


Uri u = Uri.parse("content://what_string_you_want");
return new CursorLoader(this, yourURI, projection, null, null, null) 
    private final ForceLoadContentObserver mObserver = new ForceLoadContentObserver();

    @Override
    public Cursor loadInBackground() 
        Cursor c = YOUR_DATABASE.doYourQuery(...);
        if (c != null) 
          // Ensure the cursor window is filled
           c.getCount();
           c.registerContentObserver(mObserver);
        

        c.setNotificationUri(getContext().getContentResolver(), getUri());
        return c;
    
;

在要更改数据库的代码之后,添加

 getContentResolver().notifyChange(
            Uri.parse("content://same_with_first_string"), null);

【讨论】:

【参考方案3】:

如何在共享首选项中设置一个布尔值作为假......当该布尔值为真时更新内容...... 并且当任何更改底层数据库的操作..该布尔值将设置为 true 并且作为共享首选项您是一个更改侦听器,您可以在调用相关方法后直接接收更改

【讨论】:

以上是关于android - 没有 Content Provider 的 CursorLoader 和 SQLite的主要内容,如果未能解决你的问题,请参考以下文章

c_cpp MPT - Prov.c

java.lang.IllegalArgumentException:没有为片段的 id 0x1020002 (android:id/content) 找到视图

Android studio gradle 与 firebase 同步错误:响应 204:No Content 没有内容

将熊猫多索引切片彼此分开

Android:java.lang.SecurityException:没有权限uri 0 @ content://com.android.chrome.FileProvider/BlockedFil

Android:android.R.id.content 是做啥用的?