Intereting Posts
Android Bluetooth: получить UUID обнаруженных устройств Android Video Streaming – Устройство поддерживается? Retrofit 2.0 throwing "IllegalArgumentException: параметры @Field могут использоваться только с кодировкой формы". Как сделать правильный запрос API и исправить его? USB Host Mode – разрешение доступа к устройству, но не запомнено Android. Избегайте действий, которые нужно уничтожить, просто останавливая или приостанавливая его при нажатии кнопки «Назад». Помощь в получении String Array из файла arrays.xml Как я могу добавить файлы .so в проект библиотеки андроидов, используя gradle 0.7+ Android получить местоположение от лучшего поставщика доступны Является ли использование registerReceiver в классе приложения понятным хорошей, известной практикой? Xamarin: Не удалось открыть сеанс для виртуальной машины Nexus 7 (Lollipop) Приложение не обновляется для альфа-тестеров в google play GetResources (). GetColor () устарел Как удалить контакт программно в android Как вы можете использовать загрузчик, который является анимированным счетчиком с загрузчиками изображений, такими как Glide, Picasso и т. Д.? Android gradle uploadArchives при создании

Рекомендации по экспорту нескольких таблиц с использованием поставщиков контента на Android

Я создаю приложение, где у меня есть таблица для событий и таблица для мест. Я хочу, чтобы предоставить другим приложениям доступ к этим данным. У меня есть несколько вопросов, связанных с передовыми методами для такого рода проблем.

  1. Как я должен структурировать классы базы данных? В настоящее время у меня есть классы для EventsDbAdapter и VenuesDbAdapter, которые предоставляют логику для запроса каждой таблицы, имея отдельный DbManager (расширяющий SQLiteOpenHelper) для управления версиями баз данных, создания / обновления баз данных, предоставления доступа к базе данных (getWriteable / ReadeableDatabase). Является ли это рекомендуемым решением, или мне лучше или консолидировать все в один класс (т. Е. DbManager) или разделить все, и позволить каждому адаптеру расширять SQLiteOpenHelper?

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

Большинство примеров, которые я нахожу, имеют дело только с приложениями с одной таблицей, поэтому я был бы признателен за любые указатели здесь.

Solutions Collecting From Web of "Рекомендации по экспорту нескольких таблиц с использованием поставщиков контента на Android"

Вероятно, вам немного поздно, но другие могут найти это полезным.

Сначала вам нужно создать несколько CONTENT_URI

public static final Uri CONTENT_URI1 = Uri.parse("content://"+ PROVIDER_NAME + "/sampleuri1"); public static final Uri CONTENT_URI2 = Uri.parse("content://"+ PROVIDER_NAME + "/sampleuri2"); 

Затем вы расширяете свой URI-ответчик

 private static final UriMatcher uriMatcher; static { uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); uriMatcher.addURI(PROVIDER_NAME, "sampleuri1", SAMPLE1); uriMatcher.addURI(PROVIDER_NAME, "sampleuri1/#", SAMPLE1_ID); uriMatcher.addURI(PROVIDER_NAME, "sampleuri2", SAMPLE2); uriMatcher.addURI(PROVIDER_NAME, "sampleuri2/#", SAMPLE2_ID); } 

Затем создайте свои таблицы

 private static final String DATABASE_NAME = "sample.db"; private static final String DATABASE_TABLE1 = "sample1"; private static final String DATABASE_TABLE2 = "sample2"; private static final int DATABASE_VERSION = 1; private static final String DATABASE_CREATE1 = "CREATE TABLE IF NOT EXISTS " + DATABASE_TABLE1 + " (" + _ID1 + " INTEGER PRIMARY KEY AUTOINCREMENT," + "data text, stuff text);"; private static final String DATABASE_CREATE2 = "CREATE TABLE IF NOT EXISTS " + DATABASE_TABLE2 + " (" + _ID2 + " INTEGER PRIMARY KEY AUTOINCREMENT," + "data text, stuff text);"; 

Не забудьте добавить второй DATABASE_CREATE в onCreate()

Вы будете использовать блок блокировки, чтобы определить, какая таблица используется. Это мой код вставки

 @Override public Uri insert(Uri uri, ContentValues values) { Uri _uri = null; switch (uriMatcher.match(uri)){ case SAMPLE1: long _ID1 = db.insert(DATABASE_TABLE1, "", values); //---if added successfully--- if (_ID1 > 0) { _uri = ContentUris.withAppendedId(CONTENT_URI1, _ID1); getContext().getContentResolver().notifyChange(_uri, null); } break; case SAMPLE2: long _ID2 = db.insert(DATABASE_TABLE2, "", values); //---if added successfully--- if (_ID2 > 0) { _uri = ContentUris.withAppendedId(CONTENT_URI2, _ID2); getContext().getContentResolver().notifyChange(_uri, null); } break; default: throw new SQLException("Failed to insert row into " + uri); } return _uri; } 

Вам нужно будет getType delete , update , getType и т. Д. Где бы ни предлагал ваш провайдер DATABASE_TABLE или CONTENT_URI, вы добавите случай и должны иметь DATABASE_TABLE1 или CONTENT_URI1 в одном и втором в следующем и так далее столько, сколько хотите. ,

Я рекомендую проверить исходный код для Android 2.x ContactProvider. (Которые можно найти в Интернете). Они обрабатывают запросы кросс-таблиц, предоставляя специализированные представления, которые затем запускают запросы с обратной стороны. На переднем конце они доступны для вызывающего абонента через различные URI через одного поставщика контента. Вероятно, вы также захотите предоставить класс или два для хранения констант для имен полей таблицы и строк URI. Эти классы могут быть предоставлены либо как API, либо как снижение класса, и это значительно облегчит использование приложения-потребителя.

Это немного сложнее, поэтому вы также можете проверить, как календарь, чтобы получить представление о том, что вы делаете и не нуждаетесь.

Чтобы выполнить большую часть работы, вам нужен только один адаптер базы данных и один поставщик контента на каждую базу данных (не для таблицы), но вы можете использовать несколько адаптеров / поставщиков, если хотите. Это просто усложняет ситуацию.

Один ContentProvider может обслуживать несколько таблиц, но они должны быть несколько взаимосвязаны. Это будет иметь значение, если вы собираетесь синхронизировать своих поставщиков. Если вам нужна отдельная синхронизация, скажем, «Контакты», «Почта» или «Календарь», вам понадобятся разные провайдеры для каждого из них, даже если они попадают в одну базу данных или синхронизируются с одной и той же услугой, потому что адаптеры синхронизации привязаны напрямую к Конкретный поставщик.

Насколько я могу судить, вы можете использовать только один SQLiteOpenHelper для каждой базы данных, хотя, поскольку он хранит свою метаинформацию в таблице в базе данных. Поэтому, если ваши ContentProviders доступ к одной и той же базе данных, вам придётся совместно использовать Helper.

Примечание. Это пояснение / изменение ответа, которое предоставляет Opy.

Этот подход подразделяет каждый метод insert , delete , update и getType с помощью операторов switch для обработки каждой из ваших отдельных таблиц. Вы будете использовать CASE, чтобы идентифицировать каждую таблицу (или uri) для ссылки. Каждый CASE затем сопоставляется с одной из ваших таблиц или URI. Например, TABLE1 или URI1 выбирается в CASE # 1 и т. Д. Для всех таблиц, в которых работает ваше приложение.

Вот пример подхода. Это для метода вставки. Он реализован немного иначе, чем Opy, но выполняет ту же функцию. Вы можете выбрать стиль, который вы предпочитаете. Я также хотел, чтобы вставка вернула значение, даже если вставка таблицы не удалась. В этом случае он возвращает -1 .

  @Override public Uri insert(Uri uri, ContentValues values) { int uriType = sURIMatcher.match(uri); SQLiteDatabase sqlDB; long id = 0; switch (uriType){ case TABLE1: sqlDB = Table1Database.getWritableDatabase(); id = sqlDB.insert(Table1.TABLE_NAME, null, values); getContext().getContentResolver().notifyChange(uri, null); return Uri.parse(BASE_PATH1 + "/" + id); case TABLE2: sqlDB = Table2Database.getWritableDatabase(); id = sqlDB.insert(Table2.TABLE_NAME, null, values); getContext().getContentResolver().notifyChange(uri, null); return Uri.parse(BASE_PATH2 + "/" + id); default: throw new SQLException("Failed to insert row into " + uri); return -1; } } // [END insert]