web-dev-qa-db-ja.com

ルーム永続性ライブラリとコンテンツプロバイダー

ここ数日、新しい学習に時間を費やしてきましたAndroid Architecture Components。いくつかのブログ記事、ドキュメント、チュートリアルをフォローした後、すべてのコンポーネントが明確になりました。しかし、突然、古い友人コンテンツプロバイダーがどうなっているかに気付きました。この質問を書く前にかなりの時間を費やしてきたので、私は愚かに聞こえるかもしれません。役に立つ解決策はありませんでした。とにかくここにあります。ローカルDBでアプリを構築したい場合、アプリを10倍堅牢にするためにこれが非常に役立つと考えることなく、明らかに新しいアーキテクチャコンポーネント(ライブデータ、ビューモデル、部屋)を選択します。しかし、たとえば、To To Widgetなど、DBデータに他のアプリからアクセスできるようにするには、コンテンツプロバイダーをRoomと統合するにはどうすればよいですか?

48

ところで、私は同じ質問をしました。そして、私の質問に答えるサンプル here を見つけました。それがあなたと同じことを願っています。

つまり、これはコンテンツプロバイダーのquery()メソッドから呼び出されるDAOオブジェクトにあります。

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

Cursorオブジェクトを返す方法に注目してください。その他の操作については、サンプルで詳細を確認できます。

これは、@ CommonsWareの回答の選択肢3です。

28
Mark

ローカルDBを使用してアプリを構築する場合は、明らかに新しいアーキテクチャコンポーネント(ライブデータ、ビューモデル、ルーム)を選択します。

ここでは「明らかに」という用語は使用しません。アーキテクチャコンポーネントはオプションですが、要件ではありません。

しかし、たとえば、To To Widgetなど、DBデータに他のアプリからアクセスできるようにするには、コンテンツプロバイダーをRoomと統合するにはどうすればよいですか?

アプリウィジェットは、ContentProviderとは無関係です。私見ごく少数アプリはContentProviderを介してデータベースをサードパーティに公開する必要があり、noアプリは純粋に内部目的でContentProviderを使用する必要があります。

そうは言っても、いくつかの選択肢があります。

  1. 少なくともContentProviderを介して公開されるテーブルには、Roomを使用しないでください。

  2. Roomを内部目的で使用しますが、ContentProvidergetOpenHelper()を呼び出すことにより、RoomDatabaseに対して従来のSQLiteプログラミング手法を使用します

  3. ContentProviderでRoomを使用して、取得するRoomエンティティからMatrixCursorを構築する独自のコードを記述(query()の場合)、または他の操作で使用するエンティティを作成(insert()update()delete()の場合)など)

12
CommonsWare

ルームライブラリは、コンテンツプロバイダーを特にサポートしていません。自分でコンテンツプロバイダーを作成し、Roomを使用してデータベースを照会することしかできません。

Android Architecture Componentsを使用し、SQLiteベースのコンテンツプロバイダーを使用する場合は、 Kripton Persistence Library :を許可します DBクエリからライブデータを生成するコンテンツプロバイダーを生成するなど。少なくとも最後ではありません:where条件を記述するだけでよいのに、なぜSQL全体を記述する必要があるのですか?

明確にするために、私はKripton Persistence Libraryの著者です。パーシスタンス管理の点で私のニーズにすべて合うユニークなライブラリを見つけられなかったので、私はそれを書きました(そして、はい、私はプログラミングが好きなので)。

KriptonでGoogleコンテンツプロバイダーサンプルの変換バージョンを作成しました。あなたはそれを見つけることができます こちら

読みやすくするためです。 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);

}

生成されたコンテンツプロバイダーは、DAOのメソッドをURIで公開します。明確にするために、ここでは生成されたJavaDoc(常にKriptonによる)のみを配置します。

enter image description here

its wikimy site および my articles のKriptonに関する詳細情報。

6
xcesco

投稿が遅れましたが、最近同じ問題にぶつかりました。最終的に、ローカルとコンテンツプロバイダーの両方の目的で同じRoom Databaseインスタンスを使用することになりました。

enter image description here

そのため、アプリ自体は通常どおりRoomデータベースを使用し、コンテンツプロバイダーは次のように「オープンヘルパー」でRoomデータベースを「ラップ」します。

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? {
    }
}
2
Aleksei Mulin