将Room数据库暴露给其他应用程序

时间:2018-03-11 15:37:19

标签: android android-room android-architecture-components android-livedata

Android Architectural组件引入了在本地存储应用程序数据的新概念:Room.

以前使用ContentProvider我们可以将数据库暴露给其他应用程序。我们如何对房间做同样的事情?

3 个答案:

答案 0 :(得分:5)

  

如何在使用Room创建数据库时将数据库公开给其他应用程序?

最可能的答案:使用ContentProvider。最大的区别在于您将使用RoomDatabase及其getOpenHelper()方法,而不是自己使用SQLiteOpenHelper。您可以像以前一样使用与查询,插入,更新和删除相同的方法,但SupportSQLiteDatabase的API与SQLiteDatabase的API略有不同。

没有什么可以阻止您使用ContentProvider使用@Dao方法来恢复对象,但是您必须转身并将它们转换回Cursor个对象(在这种情况下) query()),这可能是乏味的。

与非房间数据库一样,您也可以通过任何其他适合您需求的IPC机制公开Room数据库,例如具有AIDL定义接口的绑定服务。 Room与IPC机制没有直接关系,但SQLiteDatabase也没有。

答案 1 :(得分:1)

要将数据库公开给其他应用,您仍然需要ContentProvider。但是,借助Room,您可以在提供商应用程序中更轻松地访问数据库中的数据。

与Room配合使用的ContentProvider上的代码段。

您可以喜欢@lomza答案,但我建议使用@CommonsWare答案。因为它为客户提供了更大的查询数据的灵活性(如果您的业务拒绝,则可以使用@Dao进行查询)

@Nullable
@Override
public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection,
                    @Nullable String[] selectionArgs, @Nullable String sortOrder) {
    final int code = MATCHER.match(uri);

    if (code == CODE_CHEESE_DIR) {
        final Context context = getContext();
        if (context == null) {
            return null;
        }

        SQLiteQueryBuilder builder = new SQLiteQueryBuilder();
        builder.setTables(Cheese.TABLE_NAME);
        String query = builder.buildQuery(projection, selection, null, null, sortOrder, null);

        final Cursor cursor = SampleDatabase.getInstance(context)
                .getOpenHelper()
                .getWritableDatabase()
                .query(query, selectionArgs);

        cursor.setNotificationUri(context.getContentResolver(), uri);
        return cursor;
    } else {
        throw new IllegalArgumentException("Unknown URI: " + uri);
    }
}

并且假设您有这样的DAO。

@Dao
public interface ChesseDAO {

    @Query("SELECT * FROM " + Chesse.TABLE_NAME)
    LiveData<Cheese> read();

}

因此,您可以在应用程序中使用RoomContentProvider来访问数据。

直接通过ContentProvider访问数据段。

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ... someview setup...

    // test
    LoaderManager.getInstance(this).initLoader(1, null, mLoaderCallbacks);
}

private LoaderManager.LoaderCallbacks<Cursor> mLoaderCallbacks = new LoaderManager.LoaderCallbacks<Cursor>() {

        String[] projections = new String[] {
                Chesse.COLUMN_ID
                Cheese.COLUMN_NAME
        };

        @NonNull
        @Override
        public Loader<Cursor> onCreateLoader(int id, @Nullable Bundle args) {
            return new CursorLoader(
                    YourActivity.this,
                    SampleContentProvider.URI_CHEESE,
                    projections,
                    null, null, null);
        }

        @Override
        public void onLoadFinished(@NonNull Loader<Cursor> loader, Cursor cursor) {
            if (cursor != null && cursor.moveToFirst()) {
                String chesseName = cursor.getString(cursor.getColumnIndex(Cheese.COLUMN_NAME));
                Toast.makeText(YourActivity.this, chesseName, Toast.LENGTH_LONG).show();
            }
        }

        @Override
        public void onLoaderReset(@NonNull Loader<Cursor> loader) {

        }
    };

有关通过会议室访问数据的代码段

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    ... someview setup...

    // test
    SampleDatabase.getInstance(this).chesse().read().observe(this, chesse -> {
        Toast.makeText(YourActivity.this, chesse.name, Toast.LENGTH_LONG).show();
    });
}

答案 2 :(得分:0)

检查GitHub上Room with Content Providers Sample的代码。使用Room with ContentProvider并没有多大的魔力。例如,insert()看起来像这样:

$(document).on('click', function (e) {
    $target = $(event.target);
    $target.addClass('active');
});