ここ数日、新しい学習に時間を費やしてきましたAndroid Architecture Components。いくつかのブログ記事、ドキュメント、チュートリアルをフォローした後、すべてのコンポーネントが明確になりました。しかし、突然、古い友人コンテンツプロバイダーがどうなっているかに気付きました。この質問を書く前にかなりの時間を費やしてきたので、私は愚かに聞こえるかもしれません。役に立つ解決策はありませんでした。とにかくここにあります。ローカルDBでアプリを構築したい場合、アプリを10倍堅牢にするためにこれが非常に役立つと考えることなく、明らかに新しいアーキテクチャコンポーネント(ライブデータ、ビューモデル、部屋)を選択します。しかし、たとえば、To To Widgetなど、DBデータに他のアプリからアクセスできるようにするには、コンテンツプロバイダーをRoomと統合するにはどうすればよいですか?
ところで、私は同じ質問をしました。そして、私の質問に答えるサンプル 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です。
ローカルDBを使用してアプリを構築する場合は、明らかに新しいアーキテクチャコンポーネント(ライブデータ、ビューモデル、ルーム)を選択します。
ここでは「明らかに」という用語は使用しません。アーキテクチャコンポーネントはオプションですが、要件ではありません。
しかし、たとえば、To To Widgetなど、DBデータに他のアプリからアクセスできるようにするには、コンテンツプロバイダーをRoomと統合するにはどうすればよいですか?
アプリウィジェットは、ContentProvider
とは無関係です。私見ごく少数アプリはContentProvider
を介してデータベースをサードパーティに公開する必要があり、noアプリは純粋に内部目的でContentProvider
を使用する必要があります。
そうは言っても、いくつかの選択肢があります。
少なくともContentProvider
を介して公開されるテーブルには、Roomを使用しないでください。
Roomを内部目的で使用しますが、ContentProvider
でgetOpenHelper()
を呼び出すことにより、RoomDatabase
に対して従来のSQLiteプログラミング手法を使用します
ContentProvider
でRoomを使用して、取得するRoomエンティティからMatrixCursor
を構築する独自のコードを記述(query()
の場合)、または他の操作で使用するエンティティを作成(insert()
、update()
、delete()
の場合)など)
ルームライブラリは、コンテンツプロバイダーを特にサポートしていません。自分でコンテンツプロバイダーを作成し、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による)のみを配置します。
its wiki 、 my site および my articles のKriptonに関する詳細情報。
投稿が遅れましたが、最近同じ問題にぶつかりました。最終的に、ローカルとコンテンツプロバイダーの両方の目的で同じRoom Databaseインスタンスを使用することになりました。
そのため、アプリ自体は通常どおり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? {
}
}