簡體   English   中英

房間持久化庫和內容提供者

[英]Room persistence library and Content provider

最近幾天我一直在學習新的Android 架構組件 在跟進了一些博客文章、文檔和教程之后,我對每個組件都變得清晰起來。 但突然間我意識到我們的老朋友Content Provider怎么樣了。 我可能聽起來很傻,因為在寫這個問題之前我已經花了很長時間搜索,我是唯一提出這個問題的人嗎? 我沒有任何有用的解決方案。 反正就是這樣,如果我想用本地數據庫構建一個應用程序,我現在顯然會選擇新的架構組件(實時數據、視圖模型、房間),不再考慮這對使應用程序 10 倍健壯非常有幫助。 但是,如果我希望其他應用程序可以訪問我的數據庫數據,例如 To Widget 如何將 Content Provider 與 Room 集成?

順便說一下,我有同樣的問題。 我在這里找到了一個樣本回答我的問題。 希望它對你也一樣。

簡而言之,這是從內容提供者的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 選項。

如果我想用本地數據庫構建一個應用程序,我現在顯然會選擇新的架構組件(實時數據、視圖模型、房間)

我不會在那里使用“顯然”這個詞。 架構組件是一個選項,但不是必需的。

但是,如果我希望其他應用程序可以訪問我的數據庫數據,例如 To Widget 如何將 Content Provider 與 Room 集成?

應用小部件與ContentProvider無關。 恕我直言,很少有應用程序應該通過ContentProvider向第三方公開數據庫,並且沒有應用程序應該純粹出於內部目的使用ContentProvider

話雖如此,您有幾個選擇:

  1. 不要使用 Room,至少對於通過ContentProvider公開的表

  2. 將 Room 用於內部用途,然后通過在RoomDatabase上調用getOpenHelper()ContentProvider使用經典的 SQLite 編程技術

  3. ContentProvider使用 Room,編寫您自己的代碼以從您檢索的 Room 實體構建一個MatrixCursor (對於query() )或創建用於其他操作的實體(對於insert()update()delete()等)

Room Library 對 Content Provider 沒有任何特別的支持。 只能自己寫Content Provider,然后用Room查詢數據庫。

如果您想使用 Android 架構組件並且想使用基於 SQLite 的內容提供程序,請考慮使用Kripton 持久性庫:它允許從數據庫查詢生成實時數據為您生成內容提供程序等等。 最起碼但並非最后:當您只需要編寫 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);

}

生成的內容提供者使用 URI 公開 DAO 的方法。 為了清楚起見,我只把生成的 JavaDoc(總是由 Kripton 提供)放在這里。

在此處輸入圖片說明

有關 Kripton 的更多信息,請訪問其 wiki我的網站我的文章

遲到的帖子,但我最近遇到了同樣的問題。 最后最終將相同的 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? {
    }
}

你最好使用 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);
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM