web-dev-qa-db-fra.com

Bibliothèque de persistance de salle et fournisseur de contenu

Ces derniers jours, j'ai passé beaucoup de temps à apprendre de nouvelles technologies Android Architecture Components. Après avoir suivi des articles de blog, de la documentation et des tutoriels, chaque élément devenait clair pour moi. Mais tout à coup, j'ai réalisé que dire de notre vieil ami fournisseur de conten. Cela peut paraître ridicule, car avant d’écrire cette question, j’avais passé un bon moment à chercher, suis-je le seul à avoir posé cette question? Je n'avais aucune solution utile. Quoi qu'il en soit, si je veux créer une application avec une base de données locale, je choisirai évidemment de nouveaux composants d'architecture (données en direct, modèle de vue, salle) sans plus réfléchir, ce sera très utile pour rendre l'application robuste 10x. Mais si je veux que mes données de base de données soient accessibles à d'autres applications, par exemple To Widget, comment puis-je intégrer le fournisseur de contenu à Room?

48
Wubbalubbadubdub

J'ai eu la même question au fait. Et j'ai trouvé un échantillon ici qui répond à ma question. J'espère que cela fait la même chose avec vous.

En bref, cela se trouve dans l'objet DAO qui serait appelé à partir de la méthode query() du fournisseur de contenu.

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

Remarquez comment il retourne l'objet Cursor. D'autres opérations, vous pouvez voir par vous-même plus en détail dans l'exemple.

Ceci est le choix numéro 3 dans la réponse de @CommonsWare, je pense.

28
Mark

si je veux créer une application avec une base de données locale, je choisirai évidemment de nouveaux composants d'architecture (données en direct, modèle de vue, salle)

Je n'utiliserais pas le terme "évidemment" ici. Les composants d'architecture sont une option, mais pas une exigence.

Mais si je veux que mes données de base de données soient accessibles à d'autres applications, par exemple To Widget, comment puis-je intégrer le fournisseur de contenu à Room?

Un widget d'application n'a aucun lien avec un ContentProvider. IMHO très pe les applications devraient exposer leurs bases de données à des tiers via ContentProvider, et non les applications devraient utiliser un ContentProvider purement à des fins internes .

Cela étant dit, vous avez plusieurs choix:

  1. N'utilisez pas Room, au moins pour que les tables soient exposées via le ContentProvider

  2. Utilisez Room à des fins internes, mais utilisez ensuite les techniques de programmation classiques de SQLite pour ContentProvider en appelant getOpenHelper() sur votre RoomDatabase.

  3. Utilisez Room dans ContentProvider en écrivant votre propre code pour construire un MatrixCursor à partir des entités Room que vous récupérez (pour query()) ou pour créer des entités à utiliser avec d'autres opérations (pour insert(), update(), delete(), etc.)

12
CommonsWare

Room Library ne prend pas en charge le fournisseur de contenu. Vous pouvez uniquement écrire le fournisseur de contenu vous-même, puis utiliser Room pour interroger une base de données.

Si vous souhaitez utiliser Android Composants d'architecture et que vous souhaitez utiliser des fournisseurs de contenu basés sur SQLite, envisagez d'utiliser Kripton Persistence Library : cela permet de générer des données en direct à partir de requêtes de base de données, générer le fournisseur de contenu pour vous , et bien plus encore. last: pourquoi faut-il écrire l'intégralité du SQL, alors qu'il suffit d'écrire les conditions where?

Soyons clairs, je suis l'auteur de Kripton Persistence Library. Je l'ai écrit parce que je n'ai pas trouvé de bibliothèque unique qui réponde à tous mes besoins en termes de gestion de la persistance (et oui, parce que j'aime programmer).

J'ai écrit une version convertie de Google Content Provider Sample avec Kripton. Vous pouvez le trouver ici .

Juste pour simplifier la lecture. Avec Kripton, il vous suffit de définir une interface DAO. Le fournisseur de contenu sera généré par les annotations. Le même DAO converti à Kripton sera:

@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);

}

Le fournisseur de contenu généré expose la méthode de DAO avec des URI. Pour le nettoyage, je ne mets ici que le JavaDoc généré (toujours par Kripton).

enter image description here

Plus d'informations sur Kripton sur son wiki , mon site et sur mes articles .

6
xcesco

Post tardif mais je suis tombé sur le même numéro récemment. Finalement, nous avons fini par utiliser la même instance de base de données de salles à la fois comme fournisseur local et comme fournisseur de contenu.

enter image description here

Donc, l'application elle-même utilise Room Database comme d'habitude et le fournisseur de contenu "enveloppe" la base de données avec "helper ouvert" comme suit:

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