房间持久性库和内容提供商

Wub*_*dub 51 architecture android android-contentprovider android-room

最近几天我一直在花时间学习新的Android架构组件.在跟进了一些博客文章,文档和教程后,每个组件都清楚了.但突然间,我意识到我们的老朋友内容提供商.我可能听起来很傻,因为在写这个问题之前我花了很长时间搜索,我是唯一一个提出这个问题的人.我没有任何有用的解决方案.无论如何,如果我想用本地数据库构建一个应用程序,我现在显然会选择新的架构组件(实时数据,视图模型,房间),而不需要进一步思考这对于使应用程序10x强大有用非常有帮助.但是如果我希望我的数据库数据可以访问其他应用程序,例如To Widget如何将Content Provider与Room集成?

Mar*_*ark 29

顺便提一下,我有同样的问题.我在这里找到了一个样本回答我的问题.希望它和你一样.

简而言之,这是在DAO对象中,它将从Content Provider的query()方法调用.

/**
 * Select all cheeses.
 *
 * @return A {@link Cursor} of all the cheeses in the table.
 */
@Query("SELECT * FROM " + Cheese.TABLE_NAME)
Cursor selectAll();
Run Code Online (Sandbox Code Playgroud)

注意它是如何返回Cursor对象的.其他操作,您可以在示例中更详细地了解自己.

我想这是@CommonsWare在答案中的第3号选择.

  • @Mark 提到的示例是解决方案的真正瑰宝。这是一个很好的示例,展示了如何使用内容提供商和 Room 作为后端。我更进一步,通过存储库模式访问 Room;这样只有存储库正在访问 Room 数据库。如果有人需要,很乐意发布示例,但这个答案就足够了。 (2认同)

Com*_*are 13

如果我想用本地数据库构建一个应用程序,我现在显然会选择新的架构组件(实时数据,视图模型,房间)

我不会在那里使用"明显"这个词.架构组件是一个选项,但不是必需的.

但是如果我希望我的数据库数据可以访问其他应用程序,例如To Widget如何将Content Provider与Room集成?

应用小部件与a无关ContentProvider.恕我直言,很少有应用程序应该通过数据库向第三方公开数据库ContentProvider,并且没有任何应用程序应该ContentProvider纯粹用于内部目的.

话虽这么说,你有几个选择:

  1. 不要使用Room,至少要通过桌面暴露 ContentProvider

  2. 使用Room用于内部目的,然后使用经典的SQLite编程技术ContentProvider,通过调用getOpenHelper()你的RoomDatabase

  3. 使用房间的ContentProvider,编写自己的代码来建立一个MatrixCursor从您检索(用于房间实体query())或创建实体与其他操作使用(insert(),update(),delete()等)

  • @Josh:Google经常无法更新其文档.我想不出任何现在的Android应用开发专家,他们主张将ContentProvider用于纯粹的内部使用. (6认同)
  • 将ContentProvider用于内部目的是可以接受的; 特别是如果你需要使用CursorAdapters.即使这样,您也可以并且应该使用ContentProviders"因为它们提供了一个很好的抽象"[来源](https://developer.android.com/guide/topics/providers/content-providers.html),由您自行决定. (5认同)
  • @Josh:我不知道任何需要Cursor*的情况.例如,您引用了CursorAdapter.不仅有其他ListAdapter实现,但在许多情况下,RecyclerView是更好的视图选择,而RecyclerView不使用CursorAdapter. (3认同)
  • 它并不流行,因为大多数人不了解如何使用它。对我来说,这是衡量初级和中级在经验方面的差异。这真的不是太难,一旦你掌握了它的窍门,它对你来说是如此之多,值得花时间。这就是为什么您手机上的大多数主要应用程序都使用 SyncManager。 (2认同)

Ale*_*lin 7

迟到的帖子,但我最近遇到了同样的问题。最后最终将相同的 Room Database 实例用于本地和内容提供者的目的。

在此处输入图片说明

所以应用程序本身像往常一样使用房间数据库,内容提供者用“打开助手”“包装”房间数据库,如下所示:

class DatabaseProvider : ContentProvider() {

    override fun onCreate(): Boolean {
        return true
    }

    override fun query(uri: Uri?, projection: Array<out String?>?, selection: String?, selectionArgs: Array<out String?>?, sortOrder: String?): Cursor? {
        val db = roomDatabase.openHelper.readableDatabase
        db.query(...)
    }

    override fun insert(uri: Uri?, values: ContentValues?): Uri? {
        val db = roomDatabase.openHelper.writableDatabase
        db.insert(...)
    }

    override fun update(uri: Uri?, values: ContentValues?, selection: String?, selectionArgs: Array<out String?>?): Int {
        val db = roomDatabase.openHelper.writableDatabase
        db.update(...)
    }

    override fun delete(uri: Uri?, selection: String?, selectionArgs: Array<out String?>?): Int {
        val db = roomDatabase.openHelper.writableDatabase
        db.delete(...)
    }

    override fun getType(uri: Uri?): String? {
    }
}
Run Code Online (Sandbox Code Playgroud)


xce*_*sco 6

Room Library对内容提供者没有任何特定支持。您只能自己编写Content Provider,然后使用Room来查询数据库。

如果您要使用Android体系结构组件,并且要使用基于SQLite的内容提供程序,请考虑使用Kripton Persistence Library:它可以从数据库查询生成实时数据为您生成内容提供程序,等等。最少但不是最后:当只需要编写where条件时,为什么必须编写整个SQL?

明确地说,我是Kripton Persistence Library的作者。我之所以写它,是因为我没有找到一个适合我在持久性管理方面需要的唯一库(是的,因为我喜欢编程)。

我用Kripton编写了Google Content Provider Sample的转换版本。您可以在这里找到它。

只是为了简化阅读。使用Kripton,您只需要定义一个DAO接口。内容提供者将由注释生成。在Kripton中转换的同一DAO将是:

@BindContentProviderPath(path = "cheese")
@BindDao(Cheese.class)
public interface CheeseDao {

    @BindSqlSelect(fields="count(*)")
    int count();

    @BindContentProviderEntry
    @BindSqlInsert
    long insert(String name);

    @BindContentProviderEntry()
    @BindSqlSelect
    List<Cheese> selectAll();

    @BindContentProviderEntry(path = "${id}")
    @BindSqlSelect(where ="id=${id}")
    Cheese selectById(long id);

    @BindContentProviderEntry(path = "${id}")
    @BindSqlDelete(where ="id=${id}")
    int deleteById(long id);

    @BindContentProviderEntry(path = "${cheese.id}")
    @BindSqlUpdate(where="id=${cheese.id}")
    int update(Cheese cheese);

}
Run Code Online (Sandbox Code Playgroud)

生成的内容提供者使用URI公开DAO的方法。为了清楚起见,我仅将生成的JavaDoc(始终由Kripton)放在此处。

在此处输入图片说明

有关Kripton的更多信息,请访问其Wiki我的网站我的文章