Raumpersistenzbibliothek und Inhaltsanbieter

Lesezeit: 8 Minuten

In den letzten paar Tagen habe ich Zeit damit verbracht, Neues zu lernen Komponenten der Android-Architektur . Nachdem ich einige Blog-Posts, Dokumentationen und Tutorials verfolgt hatte, wurden mir alle Komponenten klar. Aber plötzlich wurde mir klar, was mit unserem alten Freund war Inhalt Anbieter . Ich mag albern klingen, denn bevor ich diese Frage geschrieben habe, habe ich ziemlich viel Zeit mit der Suche verbracht: Bin ich der einzige, der auf diese Frage gekommen ist? Ich hatte keine hilfreiche Lösung. Wie auch immer, hier ist es, wenn ich eine App mit lokaler DB aufbauen möchte, werde ich jetzt natürlich neue Architekturkomponenten (Live-Daten, Ansichtsmodell, Raum) auswählen, ohne weiter darüber nachzudenken, dass dies sehr hilfreich sein wird, um die App 10x robust zu machen. Aber wenn ich möchte, dass meine DB-Daten für andere Apps zugänglich sind, zum Beispiel To Widget Wie integriere ich Content Provider mit Room?

  • Hi, wir können die Raumdatenbank mit dem Inhaltsanbieter verbinden, gehen Sie auf die Suche in der Sharing Room Database mit Kotlin. Sie erhalten meinen Beitrag, der dasselbe erklärt

    – Anikethan Shetty

    6. August 2020 um 7:39 Uhr

  • medium.com/@aniket93shetty/…

    – Anikethan Shetty

    7. August 2020 um 7:59 Uhr

Ich hatte übrigens die gleiche Frage. Und ich habe eine Probe gefunden hier was meine Frage beantwortet. Hoffe es geht bei dir genauso.

Kurz gesagt, dies befindet sich im DAO-Objekt, das vom Inhaltsanbieter aufgerufen wird query() Methode.

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

Beachten Sie, wie es zurückkehrt Cursor Objekt. Andere Operationen können Sie sich im Beispiel genauer ansehen.

Dies hier ist, glaube ich, Auswahl Nummer 3 in der Antwort von @CommonsWare.

  • vielen Dank, ein Haufen Kumpel. Ich war verwirrt mit der letzten Antwort. Ich hatte keine Ahnung, was Matrix-Cursor ist. nachdem ich danach gesucht hatte, sagte ich mir, ok, lass es. jetzt deine antwort und der github-link, den du gegeben hast; wäre ein hilfreicher vorschlag. Ich freue mich immer über Proben.

    – Wubbalubbadubdub

    23. Oktober 2017 um 7:13 Uhr

  • Sie können auch eine Liste der Entitäten direkt von DAO erhalten, um Inhaltsanbieter zu vermeiden. Sie würden einfach alles in DAO in eine AsyncTask packen, und Sie können loslegen.

    – JustMeh

    19. Juli 2018 um 7:55 Uhr

  • Dies funktioniert nur, wenn Sie Daten für andere Apps bereitstellen, aber es hilft Ihnen nicht, wenn Sie Daten von anderen Apps nutzen möchten. Dies ist eine große Lücke in Unterstützter Kommunikation.

    – Brillant Pappin

    20. September 2018 um 16:28 Uhr

  • Das Beispiel, das @Mark erwähnt, ist das wahre Juwel der Lösung. Es ist ein großartiges Beispiel dafür, wie man einen Inhaltsanbieter und Room als Back-End verwendet. Ich ging noch ein bisschen weiter und greife über das Repository-Muster auf Room zu. sodass nur das Repository auf die Room-Datenbank zugreift. Gerne poste ich Beispiele, wenn jemand Bedarf hat, aber diese Antwort ist ausreichend.

    – Todd DeLand

    5. Februar 2019 um 14:13 Uhr


  • Danke für den Hinweis auf die Proben. Ist es sinnvoll, die Dao-Injektion in den Inhaltsanbieter mit Dolch zu verwenden?

    – a_chubenko

    6. August 2019 um 16:42 Uhr

Wenn ich eine App mit lokaler DB aufbauen möchte, wähle ich jetzt natürlich neue Architekturkomponenten (Live-Daten, Ansichtsmodell, Raum)

Den Begriff “offensichtlich” würde ich da nicht verwenden. Die Architekturkomponenten sind eine Option, aber keine Voraussetzung.

Aber wenn ich möchte, dass meine DB-Daten für andere Apps zugänglich sind, zum Beispiel To Widget Wie integriere ich Content Provider mit Room?

Ein App-Widget hat nichts mit einem zu tun ContentProvider. meiner bescheidenen Meinung nach Sehr wenig Apps sollten Datenbanken für Dritte offen legen über ContentProviderund nein Apps sollten eine verwenden ContentProvider rein für interne Zwecke.

Davon abgesehen haben Sie einige Möglichkeiten:

  1. Verwenden Sie keinen Raum, zumindest für die Tabellen, die über die belichtet werden sollen ContentProvider

  2. Verwenden Sie Room für interne Zwecke, verwenden Sie dann aber klassische SQLite-Programmiertechniken für die ContentProviderper Anruf getOpenHelper() auf Ihrem RoomDatabase

  3. Verwenden Sie Zimmer in der ContentProviderSchreiben Sie Ihren eigenen Code, um a aufzubauen MatrixCursor aus den Room-Entitäten, die Sie abrufen (z query()) oder Erstellen der Entitäten zur Verwendung mit anderen Vorgängen (z insert(), update(), delete()etc.)

  • Es ist akzeptabel, einen ContentProvider für interne Zwecke zu verwenden; insbesondere wenn Sie mit CursorAdaptern arbeiten müssen. Auch dann können und sollten Sie ContentProvider verwenden, “weil sie eine schöne Abstraktion bieten”. Quelle in Ihrem Ermessen.

    – Josch

    16. November 2017 um 1:26 Uhr


  • @Josh: Google versäumt es oft, seine Dokumentation zu aktualisieren. Mir fällt kein aktueller Experte für die Entwicklung von Android-Apps ein, der die Verwendung von ContentProvider für den rein internen Gebrauch befürwortet.

    – CommonsWare

    16. November 2017 um 1:30 Uhr

  • @Josh: Mir ist kein Fall bekannt, wo ein Cursor ist erforderlich. Beispielsweise haben Sie CursorAdapter zitiert. Es gibt nicht nur andere ListAdapter-Implementierungen, sondern RecyclerView ist in vielen Fällen eine bessere Ansichtswahl, und RecyclerView verwendet CursorAdapter nicht.

    – CommonsWare

    16. November 2017 um 2:20 Uhr

  • Ich verwende ContentProviders in allen meinen datenbankgesteuerten Apps, auch nur für den internen Gebrauch. Der Hauptgrund dafür ist die Thread-sichere Implementierung. Sicher, es fügt aus Sicht der Entwicklung ein wenig Overhead hinzu, aber die Vorteile überwiegen bei weitem. Genauso einfach lässt sich die RecyclerView.Adapter-Klasse um die CursorAdapter-Funktionalität erweitern. Sobald Sie das getan haben, ist die Verwendung eines ContentProviders meiner Meinung nach einfacher als der direkte Zugriff auf eine lokale Datenbank, insbesondere ohne die Thread-sicheren Aspekte.

    – Baron

    28. November 2017 um 18:34 Uhr

  • Es ist nicht beliebt, weil die meisten Leute nicht verstehen, wie man es benutzt. Für mich ist es ein Maß für den Erfahrungsunterschied zwischen einem Junior und einem Intermediate. Es ist wirklich nicht zu schwer, wenn man den Dreh raus hat, und es ist so viel für einen, dass es die Zeit wert ist. Aus diesem Grund verwenden die meisten primären Apps auf Ihrem Telefon den SyncManager.

    – Brillant Pappin

    15. Juli 2018 um 21:32 Uhr


Benutzer-Avatar
xcesco

Die Raumbibliothek bietet keine besondere Unterstützung für Inhaltsanbieter. Sie können Content Provider nur selbst schreiben und dann Room verwenden, um eine Datenbank abzufragen.

Wenn Sie Android-Architekturkomponenten verwenden und mit SQLite-basierten Inhaltsanbietern arbeiten möchten, ziehen Sie die Verwendung von in Betracht Kripton Persistenzbibliothek: es erlaubt Live-Daten generieren aus DB-Abfragen, Content Provider für Sie generieren, und vieles mehr. Last but not least: Warum müssen Sie das gesamte SQL schreiben, wenn Sie nur die Where-Bedingungen schreiben müssen?

Nur um das klarzustellen, ich bin der Autor der Kripton Persistence Library. Ich habe es geschrieben, weil ich keine einzigartige Bibliothek gefunden habe, die alle meine Anforderungen in Bezug auf die Persistenzverwaltung erfüllt (und ja, weil ich gerne programmiere).

Ich habe eine konvertierte Version von Google Content Provider Sample mit Kripton geschrieben. Sie können es finden hier.

Nur um das Lesen zu vereinfachen. Bei Kripton müssen Sie nur eine DAO-Schnittstelle definieren. Inhaltsanbieter werden durch die Anmerkungen generiert. Dasselbe DAO, das in Kripton konvertiert wird, lautet:

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

}

Der generierte Inhaltsanbieter macht die DAO-Methode mit URIs verfügbar. Zur Verdeutlichung stelle ich hier nur das generierte JavaDoc (immer von Kripton) ein.

Geben Sie hier die Bildbeschreibung ein

Weitere Informationen zu Kripton auf sein Wiki, meine Seite und weiter meine Artikel .

Verspäteter Beitrag, aber ich bin kürzlich auf dieselbe Ausgabe gestoßen. Letztendlich wurde dieselbe Raumdatenbankinstanz sowohl für lokale als auch für Inhaltsanbieterzwecke verwendet.

Geben Sie hier die Bildbeschreibung ein

Die App selbst verwendet also die Raumdatenbank wie gewohnt und der Inhaltsanbieter “wrapst” die Raumdatenbank mit “open helper” wie folgt:

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? {
    }
}

Benutzer-Avatar
Jaja

Verwenden Sie besser den SupportOpenHelper

public class MyContentProvider extends ContentProvider {
    public MyContentProvider() {
    }

    @Override
    public String getType(Uri uri) {
        // TODO: Implement this to handle requests for the MIME type of the data
        // at the given URI.
        throw new UnsupportedOperationException("Not yet implemented");
    }

    UserDatabase database;

    @Override
    public boolean onCreate() {
        database = Room.databaseBuilder(getContext(), UserDatabase.class, "user.db").allowMainThreadQueries().build();
        return false;
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
         return database.query(SupportSQLiteQueryBuilder.builder("user").selection(selection, selectionArgs).columns(projection).orderBy(sortOrder).create());
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
        return database.getOpenHelper().getWritableDatabase().update("user", 0, values, selection, selectionArgs);
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        return database.getOpenHelper().getWritableDatabase().delete("user", selection, selectionArgs);
    }

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        long retId = database.getOpenHelper().getWritableDatabase().insert("user", 0, values);
        return ContentUris.withAppendedId(uri, retId);
    }
}

1227300cookie-checkRaumpersistenzbibliothek und Inhaltsanbieter

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy