Собственный ContentProvider с SQLite и несколькими таблицами

Я читаю этот учебник о реализации моего собственного ContentProvide для работы с SQLite. Int ContentProvider.query есть несколько вещей, которые меня озадачивают. Кажется очень жестко привязано к одной таблице (таблица todo в учебнике), но, может быть, я просто не получаю ее? Теперь, если я хочу запросить другую таблицу, скажем nodo, как мне изменить ContentProvider?

Должен ли я добавлять имена таблиц так или иначе в queryBuilder.setTables(String inTables)?

Как насчет CONTENT_TYPE и CONTENT_ITEM_TYPE, должен ли быть один для каждой таблицы?

Что о вариантах TODO и TODO_ID и о переключателе в методе запроса?

Кажется, мне нужно иметь много условий if/switch для поддержки нескольких таблиц с тем же ContentProvider, это способ пойти или я ошибаюсь?

Спасибо.
Сорен

Ответ 1

Теперь, если бы я хотел запросить другую таблицу, скажем nodo, как я могу изменить ContentProvider?

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

Вы добавили бы по существу все жестко установленные значения, которые уже существуют для todos для вашей другой таблицы. Например:

// ------- usually the same for all
private static final String AUTHORITY = "de.vogella.android.todos.contentprovider";

// ------- define some Uris
private static final String PATH_TODOS = "todos";
private static final String PATH_REMINDERS = "reminders";

public static final Uri CONTENT_URI_TODOS = Uri.parse("content://" + AUTHORITY
    + "/" + PATH_TODOS);
public static final Uri CONTENT_URI_REMINDERS = Uri.parse("content://" + AUTHORITY
        + "/" + PATH_REMINDERS);

// ------- maybe also define CONTENT_TYPE for each

// ------- setup UriMatcher
private static final int TODOS = 10;
private static final int TODO_ID = 20;
private static final int REMINDERS = 30;
private static final int REMINDERS_ID = 40;
private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH);
static {
  sURIMatcher.addURI(AUTHORITY, PATH_TODOS, TODOS);
  sURIMatcher.addURI(AUTHORITY, PATH_TODOS + "/#", TODO_ID);
  sURIMatcher.addURI(AUTHORITY, PATH_REMINDERS, REMINDERS);
  sURIMatcher.addURI(AUTHORITY, PATH_REMINDERS + "/#", REMINDERS_ID);
}

//@Override
public Cursor query(Uri uri, String[] projection, String selection,
        String[] selectionArgs, String sortOrder) {

    // Using SQLiteQueryBuilder instead of query() method
    SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();

    int uriType = sURIMatcher.match(uri);
    switch (uriType) {

        case TODO_ID:
            // Adding the ID to the original query
            queryBuilder.appendWhere(TodoTable.COLUMN_ID + "="
                    + uri.getLastPathSegment());
            //$FALL-THROUGH$
        case TODOS:
            queryBuilder.setTables(TodoTable.TABLE_TODO);
            break;

        case REMINDERS_ID:
            // Adding the ID to the original query
            queryBuilder.appendWhere(ReminderTable.COLUMN_ID + "="
                    + uri.getLastPathSegment());
            //$FALL-THROUGH$
        case REMINDERS:
            queryBuilder.setTables(ReminderTable.TABLE_REMINDER);
            break;

        default:
            throw new IllegalArgumentException("Unknown URI: " + uri);
  }

Должен ли я добавлять имена таблиц так или иначе в queryBuilder.setTables(String inTables)?

Да, если разные Uri читать из разных таблиц, тогда установите таблицу на основе совпадения Uri.

Как насчет CONTENT_TYPE и CONTENT_ITEM_TYPE, должен ли быть один для каждой таблицы?

Зависит от фактического типа содержимого. Если они разные, и вам нужен тип да. Но вам не нужно их вообще. Этот пример определяет их, но даже не использует их. Он должен будет вернуть тип в getType, см. документацию.

Что о вариантах TODO и TODO_ID и о переключателе в методе запроса?

Это константы, определенные для UriMatcher, которые объясняются здесь . Это в основном упрощение для сопоставления строк. Большой ContentProvider может иметь 100 разных Uris и выбор правильной таблицы в query будет болезненным, если вам придется писать if (uri.getPath().equals("todos") { /* code */ } else if (uri.. полностью.

Ответ 2

Здесь решение на ваш вопрос, используя UriMatcher, вы можете реализовать несколько таблиц в поставщике контента.

Ответ 3

Тип контента и элемент контента могут быть следующими и их можно обернуть в отдельный класс для каждой таблицы

public static final String GENERAL_CONTENT_TYPE = "vnd.android.cursor.dir/vnd.myfirstapp.db.member" ; public static final String SPECIFIC_CONTENT_TYPE = "vnd.android.cursor.item/vnd.myfirstapp.db.member" ;

`vnd.android.cursor.dir/vnd.yourownanything.anything.tablename

определяет общий тип содержимого `Vnd.android.cursor.item/vnd.anthingasabove.table" это также определяет конкретную и постоянную для любого приложения эти строки (слова) vnd.android.cursor.dir и .item должны быть такими и после /vnd. должен быть таким, что

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