Предложения пользовательского поиска Android: запрос двух параметров

Структура SQLite

Table: Class

 Column1: classID (primary key)
 Column2: className


Table: Students

 Column1: studentID (primary key)
 Column2: classID (foreign key)
 Column3: studentName

Вопрос

Я следовал инструкциям разработчика Adding Custom Suggestions. Система правильно вызывает функцию запроса моего провайдера контента, когда я печатаю в виджете поиска на панели действий, и я вижу подсказки поиска. Моя проблема в том, что запрос возвращает предложения из всей таблицы студентов (что является ожидаемым поведением). Но мне нужно ограничить количество предложений для данного classID. Но так, как работают предложения поиска, как описано в руководстве разработчика, в функцию запроса передается только один параметр, который в моем случае - selectionArgs [0].

searchable.xml

<?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
    android:hint="@string/student_search_hint"
    android:label="@string/app_name"
    android:searchSuggestThreshold="2"
    android:searchSuggestAuthority="com.androidapp.providers.database"
    android:searchSuggestSelection="studentName LIKE ? "
    android:searchSuggestIntentAction="android.intent.action.VIEW"
    android:searchMode="queryRewriteFromText" >

выдержка из контент-провайдера

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

    ...

    queryBuilder.setTables(StudentsTable.TABLE);

    HashMap<String, String> columnMap = new HashMap<String, String>();
    columnMap.put(BaseColumns._ID, StudentsTable.STUDENT_ID + " AS " + BaseColumns._ID);
    columnMap.put(SearchManager.SUGGEST_COLUMN_TEXT_1, StudentsTable.NAME + " AS " + SearchManager.SUGGEST_COLUMN_TEXT_1);
    columnMap.put(SearchManager.SUGGEST_COLUMN_INTENT_DATA, StudentsTable.STUDENT_ID + " AS " + SearchManager.SUGGEST_COLUMN_INTENT_DATA);
    queryBuilder.setProjectionMap(columnMap);

    limit = uri.getQueryParameter(SearchManager.SUGGEST_PARAMETER_LIMIT);
    selectionArgs[0] = "%"+selectionArgs[0] + "%";

    SQLiteDatabase db = database.getWritableDatabase();
    Cursor cursor = queryBuilder.query(db, projection, selection, selectionArgs, null, null, sortOrder, limit);

    return cursor;
}

Если бы запрос был инициирован мной, я мог бы просто передать второй параметр (classID) в selectionArgs[1] и соответствующим образом изменить строку выбора, чтобы сформировать правильный оператор SQLite.

Но запрос инициируется системой. Так как мне это сделать? Есть ли возможность перехватить вызов моего провайдера контента и изменить запрос на запрос?

2 ответа

Решение

Я надеюсь, что это кому-то пригодится, я потратил несколько дней, пытаясь понять это, благодаря ссылке, предоставленной pskink, я смог реализовать следующее решение:

Я создал переменную в поставщике контента и соответствующий метод установки:

public class MyContentProvider extends ContentProvider {

    ...

    private long id;

    ...

    public void setId(long id) {
        this.id = id;     
    }

}

Затем в своей деятельности, где я хочу предоставить предложения по поиску только для учащихся определенного класса, я делаю:

ContentProviderClient client = getContentResolver().acquireContentProviderClient("com.androidapp.providers.database");
MyContentProvider provider = (MyContentProvider)client.getLocalContentProvider();
provider.setId(rowid); //rowid is the classId from which students will be searched
client.release();

Изменить функцию запроса:

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

    ...

    queryBuilder.setTables(StudentsTable.TABLE);

    HashMap<String, String> columnMap = new HashMap<String, String>();
    columnMap.put(BaseColumns._ID, StudentsTable.STUDENT_ID + " AS " + BaseColumns._ID);
    columnMap.put(SearchManager.SUGGEST_COLUMN_TEXT_1, StudentsTable.NAME + " AS " + SearchManager.SUGGEST_COLUMN_TEXT_1);
    columnMap.put(SearchManager.SUGGEST_COLUMN_INTENT_DATA, StudentsTable.STUDENT_ID + " AS " + SearchManager.SUGGEST_COLUMN_INTENT_DATA);
    queryBuilder.setProjectionMap(columnMap);

    limit = uri.getQueryParameter(SearchManager.SUGGEST_PARAMETER_LIMIT);
    selectionArgs[0] = "%" + selectionArgs[0] + "%";

    /*AMMENDMENT*/
    selection = selection + "AND " + StudentsTable.CLASS_ID + "=" + id;
    //This forms the SQL statement "WHERE studentName LIKE ? AND classId=3" (Assuming that rowid was 3).
    //As per normal Android behaviour the "?" mark will be replaced by selectionArgs[0].
    /*END*/

    SQLiteDatabase db = database.getWritableDatabase();
    Cursor cursor = queryBuilder.query(db, projection, selection, selectionArgs, null, null, sortOrder, limit);

    return cursor;
}

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

Другие вопросы по тегам