Предоставление доступа к базе данных Room другим приложениям

Компоненты архитектуры Android представили новую концепцию локального хранения данных приложения: Room.

Ранее, используя ContentProvider, мы могли открывать базу данных для других приложений. Как сделать то же самое с комнатой?


person chait    schedule 11.03.2018    source источник


Ответы (3)


Как открыть базу данных для других приложений, когда мы создаем базу данных с помощью Room?

Наиболее вероятный ответ: используйте ContentProvider. Самая большая разница в том, что вы будете использовать свой RoomDatabase и его getOpenHelper() метод, а не работать с SQLiteOpenHelper самостоятельно. Для запросов, вставок, обновлений и удалений вы должны использовать те же методы, что и раньше, хотя API SupportSQLiteDatabase немного отличается от API SQLiteDatabase.

Ничто не мешает вам ContentProvider использовать @Dao методы для возврата объектов, но тогда вам нужно развернуться и преобразовать их обратно в Cursor объекты (в случае query()), а это может быть утомительно.

Как и в случае с базами данных, не относящимися к Room, вы также можете предоставлять доступ к базам данных Room через любой другой механизм IPC, который соответствует вашим потребностям, например связанный сервис с интерфейсом, определенным AIDL. Room не имеет прямого отношения к этим механизмам IPC, но и SQLiteDatabase тоже.

person CommonsWare    schedule 11.03.2018

Чтобы предоставить доступ к базе данных другим приложениям, вам все равно понадобится ContentProvider. Но с помощью Room вы можете упростить доступ к данным в вашей базе данных в приложении вашего провайдера.

Фрагмент ContentProvider, который работает с Room.

вы можете сделать как ответ @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();

}

Итак, вы в приложении можете получить доступ к данным с помощью Room или ContentProvider на ваше усмотрение.

Фрагмент доступа к данным напрямую через 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();
    });
}
person Jongz Puangput    schedule 16.01.2019

Проверьте код Образец комнаты с поставщиками контента на GitHub. В использовании Room с ContentProvider нет особого волшебства. Например, insert () выглядит так:

@Nullable
@Override
public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
    switch (MATCHER.match(uri)) {
        case CODE_CHEESE_DIR:
            final Context context = getContext();
            if (context == null) {
                return null;
            }
            final long id = SampleDatabase.getInstance(context).cheese()
                    .insert(Cheese.fromContentValues(values));
            context.getContentResolver().notifyChange(uri, null);
            return ContentUris.withAppendedId(uri, id);
        case CODE_CHEESE_ITEM:
            throw new IllegalArgumentException("Invalid URI, cannot insert with ID: " + uri);
        default:
            throw new IllegalArgumentException("Unknown URI: " + uri);
    }
}
person lomza    schedule 03.04.2018
comment
Привет, обратитесь, medium.com/@aniket93shetty/ - person Anikethan Shetty; 07.08.2020