Компоненты архитектуры Android представили новую концепцию локального хранения данных приложения: Room.
Ранее, используя ContentProvider
, мы могли открывать базу данных для других приложений. Как сделать то же самое с комнатой?
Компоненты архитектуры Android представили новую концепцию локального хранения данных приложения: Room.
Ранее, используя ContentProvider
, мы могли открывать базу данных для других приложений. Как сделать то же самое с комнатой?
Как открыть базу данных для других приложений, когда мы создаем базу данных с помощью Room?
Наиболее вероятный ответ: используйте ContentProvider
. Самая большая разница в том, что вы будете использовать свой RoomDatabase
и его getOpenHelper()
метод, а не работать с SQLiteOpenHelper
самостоятельно. Для запросов, вставок, обновлений и удалений вы должны использовать те же методы, что и раньше, хотя API SupportSQLiteDatabase
немного отличается от API SQLiteDatabase
.
Ничто не мешает вам ContentProvider
использовать @Dao
методы для возврата объектов, но тогда вам нужно развернуться и преобразовать их обратно в Cursor
объекты (в случае query()
), а это может быть утомительно.
Как и в случае с базами данных, не относящимися к Room, вы также можете предоставлять доступ к базам данных Room через любой другой механизм IPC, который соответствует вашим потребностям, например связанный сервис с интерфейсом, определенным AIDL. Room не имеет прямого отношения к этим механизмам IPC, но и SQLiteDatabase
тоже.
Чтобы предоставить доступ к базе данных другим приложениям, вам все равно понадобится 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();
});
}
Проверьте код Образец комнаты с поставщиками контента на 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);
}
}