Android的ContentProvider的双重目的:1.搜索提供商2.列出内容提供商 [英] Dual purpose of Android ContentProvider: 1. Search provider and 2. List content provider

查看:148
本文介绍了Android的ContentProvider的双重目的:1.搜索提供商2.列出内容提供商的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


  1. 我有一个的ContentProvider ,抽象我使用了的CursorAdapter 来填充的信息名单。


  2. 我建立一个搜索查看操作栏中,并要附加一个搜索的ContentProvider 来它。我可以使用此相同的供应商?它是好的设计?
    搜索查看的内容将是相同#1,它只是用于搜索项的列表视图庞大


的ContentProvider code是如下:

 公共类WebSitesContentProvider扩展ContentProvider的{    //数据库
    私人UserDatabaseHelper数据库;    //用于在UriMacher
    私有静态最终诠释TOTAL_ELEMENTS = 10;
    私有静态最终诠释ELEMENT_ID = 20;    私有静态最后弦乐BASE_PATH =网站;
    公共静态最终乌里CONTENT_URI = Uri.parse(内容://+ Consts.AUTHORITY +/+ BASE_PATH);
    公共静态最后弦乐CONTENT_TYPE = ContentResolver.CURSOR_DIR_BASE_TYPE +/网站;
    公共静态最后弦乐CONTENT_ITEM_TYPE = ContentResolver.CURSOR_ITEM_BASE_TYPE + Consts.TABLE_WEBSITES_INFO;    私有静态最终UriMatcher sURIMatcher =新UriMatcher(UriMatcher.NO_MATCH);
    静态的 {
        sURIMatcher.addURI(Consts.AUTHORITY,BASE_PATH,TOTAL_ELEMENTS);
        sURIMatcher.addURI(Consts.AUTHORITY,BASE_PATH +/#,ELEMENT_ID);
    }    @覆盖
    公共布尔的onCreate(){
        数据库=新UserDatabaseHelper(的getContext());
        返回false;
    }    @覆盖
    公共字符串的getType(URI URI){
        返回null;
    }    @覆盖
    公共光标查询(URI URI,字符串[]投影,字符串的选择,
            的String [] selectionArgs两个,字符串中将sortOrder){        //使用SQLiteQueryBuilder而不是query()方法
        SQLiteQueryBuilder的QueryBuilder =新SQLiteQueryBuilder();        //检查主叫方已请求不存在的列
        checkColumns(凸起);        // 布置桌面
        queryBuilder.setTables(Consts.TABLE_WEBSITES_INFO);        INT uriType = sURIMatcher.match(URI);
        开关(uriType){
        案例TOTAL_ELEMENTS:
            打破;
        案例ELEMENT_ID:
            //添加ID给原始查询
            queryBuilder.appendWhere(Consts.COLUMN_ID +=+ uri.getLastPathSegment());
            打破;
        默认:
            抛出新抛出:IllegalArgumentException(未知URI:+ URI);
        }        SQLiteDatabase分贝= database.getWritableDatabase();
        光标光标= queryBuilder.query(分贝,投影,选择,selectionArgs两个,NULL,NULL,中将sortOrder);
        //确保潜在的听众越来越通知
        cursor.setNotificationUri(的getContext()getContentResolver(),URI);        返回游标;
    }    @覆盖
    公共乌里插入(URI URI,ContentValues​​值){
        INT uriType = sURIMatcher.match(URI);
        SQLiteDatabase SQLDB = database.getWritableDatabase();        INT rowsDeleted = 0;
        长ID = 0;
        开关(uriType){
        案例TOTAL_ELEMENTS:
            ID = sqlDB.insert(Consts.TABLE_WEBSITES_INFO,空,价值);
            打破;
        默认:
            抛出新抛出:IllegalArgumentException(未知URI:+ URI);
        }
        的getContext()getContentResolver()有NotifyChange(URI,空)。
        返回Uri.parse(BASE_PATH +/+ ID);
    }    @覆盖
    公众诠释删除(URI URI,选择字符串,字符串[] selectionArgs两个){
        INT uriType = sURIMatcher.match(URI);
        SQLiteDatabase SQLDB = database.getWritableDatabase();
        INT rowsDeleted = 0;
        开关(uriType){
        案例TOTAL_ELEMENTS:
            rowsDeleted = sqlDB.delete(Consts.TABLE_WEBSITES_INFO,
                    选择,
                    selectionArgs两个);
            打破;
        案例ELEMENT_ID:
            字符串ID = uri.getLastPathSegment();
            如果(TextUtils.isEmpty(选择)){
                rowsDeleted = sqlDB.delete(Consts.TABLE_WEBSITES_INFO,
                        Consts.COLUMN_ID +=+编号,
                        空值);
            }其他{
                rowsDeleted = sqlDB.delete(Consts.TABLE_WEBSITES_INFO,
                        Consts.COLUMN_ID +=+ ID +和+选择,
                        selectionArgs两个);
            }
            打破;
        默认:
            抛出新抛出:IllegalArgumentException(未知URI:+ URI);
        }
        / *
         *让我们不要对小于1删除每个删除会导致网络电话通知的内容观察员。
         *用户可以一次删除多个条目。如果删除是大于1,那么它可能是一个
         *要求删除整个列表,这一点,我们将允许
         * /
        //如果(rowsDeleted→1)
            的getContext()getContentResolver()有NotifyChange(URI,空)。
        返回rowsDeleted;
    }    @覆盖
    公众诠释更新(开放的URI,ContentValues​​价值观,选择字符串,字符串[] selectionArgs两个){        INT uriType = sURIMatcher.match(URI);
        SQLiteDatabase SQLDB = database.getWritableDatabase();
        INT rowsUpdated = 0;
        开关(uriType){
        案例TOTAL_ELEMENTS:
            rowsUpdated = sqlDB.update(Consts.TABLE_WEBSITES_INFO,
                    值,
                    选择,
                    selectionArgs两个);
            打破;
        案例ELEMENT_ID:
            字符串ID = uri.getLastPathSegment();
            如果(TextUtils.isEmpty(选择)){
                rowsUpdated = sqlDB.update(Consts.TABLE_WEBSITES_INFO,
                        值,
                        Consts.COLUMN_ID +=+编号,
                        空值);
            }其他{
                rowsUpdated = sqlDB.update(Consts.TABLE_WEBSITES_INFO,
                        值,
                        Consts.COLUMN_ID +=+ ID +和+选择,
                        selectionArgs两个);
            }
            打破;
        默认:
            抛出新抛出:IllegalArgumentException(未知URI:+ URI);
        }
        的getContext()getContentResolver()有NotifyChange(URI,空)。
        返回rowsUpdated;
    }    私人无效checkColumns(字符串[]投影){
        的String [] =可用{
                Consts.COLUMN_USER,
                Consts.COLUMN_ID
        };
        如果(投影!= NULL){
            HashSet的<串GT; requestedColumns =新的HashSet<串GT;(Arrays.asList(投影));
            HashSet的<串GT; availableColumns =新的HashSet<串GT;(Arrays.asList(可用));
            //检查这些要求所有列可用
            如果(!availableColumns.containsAll(requestedColumns)){
                抛出新抛出:IllegalArgumentException(投影未知列);
            }
        }
    }
}

更新

的ContentProvider 是通用的,我同意这一点。
它们可以适应。
所以我适应我的处理搜索查看数据内容。

下面是整个的ContentProvider 同时充当一个搜索查看内容提供商和的ListView 的光标适配器有兴趣的人:

 包org.jefferyemanuel.database;进口java.util.Arrays中;
进口java.util.HashSet中;进口org.jefferyemanuel.bulkwebsites.Consts;
进口org.jefferyemanuel.bulkwebsites.Utils;进口android.app.SearchManager;
进口android.content.ContentProvider;
进口android.content.ContentResolver;
进口android.content.ContentValues​​;
进口android.content.UriMatcher;
进口android.database.Cursor;
进口android.database.MatrixCursor;
进口android.database.sqlite.SQLiteDatabase;
进口android.database.sqlite.SQLiteQueryBuilder;
进口android.net.Uri;
进口android.provider.BaseColumns;
进口android.text.TextUtils;
进口android.util.Log;公共类WebSitesContentProvider扩展ContentProvider的{    / *定义了搜索服务提供商的结构* /
    //为搜索建议UriMatcher不变
    私有静态最终诠释SEARCH_SUGGEST = 1;
    私有静态最后的String [] = SEARCH_SUGGEST_COLUMNS {
            BaseColumns._ID,
            SearchManager.SUGGEST_COLUMN_TEXT_1,
            SearchManager.SUGGEST_COLUMN_INTENT_DATA,
            SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA,
            SearchManager.SUGGEST_COLUMN_SHORTCUT_ID
    };    //数据库
    私人UserDatabaseHelper数据库;    //用于在UriMacher
    私有静态最终诠释TOTAL_ELEMENTS = 10;
    私有静态最终诠释ELEMENT_ID = 20;    私有静态最后弦乐BASE_PATH =网站;
    公共静态最终乌里CONTENT_URI = Uri.parse(内容://+ Consts.AUTHORITY +/+ BASE_PATH);    公共静态最后弦乐CONTENT_TYPE = ContentResolver.CURSOR_DIR_BASE_TYPE +/网站;
    公共静态最后弦乐CONTENT_ITEM_TYPE = ContentResolver.CURSOR_ITEM_BASE_TYPE + Consts.TABLE_WEBSITES_INFO;    私有静态最终UriMatcher sURIMatcher =新UriMatcher(UriMatcher.NO_MATCH);
    静态的 {
        sURIMatcher.addURI(Consts.AUTHORITY,BASE_PATH,TOTAL_ELEMENTS);
        sURIMatcher.addURI(Consts.AUTHORITY,BASE_PATH +/#,ELEMENT_ID);        sURIMatcher.addURI(Consts.AUTHORITY,SearchManager.SUGGEST_URI_PATH_QUERY,SEARCH_SUGGEST);
        sURIMatcher.addURI(Consts.AUTHORITY,SearchManager.SUGGEST_URI_PATH_QUERY +/ *,SEARCH_SUGGEST);
    }    @覆盖
    公共布尔的onCreate(){
        数据库=新UserDatabaseHelper(的getContext());
        返回false;
    }    @覆盖
    公共字符串的getType(URI URI){
        返回null;
    }    @覆盖
    公共光标查询(URI URI,字符串[]投影,选择字符串,字符串[] selectionArgs两个,字符串中将sortOrder){        //使用SQLiteQueryBuilder而不是query()方法
        SQLiteQueryBuilder的QueryBuilder =新SQLiteQueryBuilder();        //检查主叫方已请求不存在的列
        checkColumns(凸起);        // 布置桌面
        queryBuilder.setTables(Consts.TABLE_WEBSITES_INFO);        INT uriType = sURIMatcher.match(URI);
        开关(uriType){
        案例TOTAL_ELEMENTS:
            打破;        案例SEARCH_SUGGEST:
            queryBuilder.appendWhere(Consts.COLUMN_NAME +LIKE'%+ uri.getLastPathSegment()+%');
            打破;        案例ELEMENT_ID:
            //添加ID给原始查询
            queryBuilder.appendWhere(Consts.COLUMN_ID +=+ uri.getLastPathSegment());
            打破;
        默认:
            抛出新抛出:IllegalArgumentException(未知URI:+ URI);
        }        SQLiteDatabase分贝= database.getWritableDatabase();
        光标光标= queryBuilder.query(分贝,投影,选择,selectionArgs两个,NULL,NULL,中将sortOrder);        / *
         *如果这个请求来自搜索查看再转换光标移动到搜索矩阵光标。
         * /
        如果(uriType == SEARCH_SUGGEST)
            光标= buildSearchMatrixCursorFromStandardCursor(光标);        //确保潜在的听众越来越通知
        cursor.setNotificationUri(的getContext()getContentResolver(),URI);        返回游标;
    }    @覆盖
    公共乌里插入(URI URI,ContentValues​​值){
        INT uriType = sURIMatcher.match(URI);
        SQLiteDatabase SQLDB = database.getWritableDatabase();        INT rowsDeleted = 0;
        长ID = 0;
        开关(uriType){
        案例TOTAL_ELEMENTS:
            ID = sqlDB.insert(Consts.TABLE_WEBSITES_INFO,空,价值);
            打破;
        默认:
            抛出新抛出:IllegalArgumentException(未知URI:+ URI);
        }
        的getContext()getContentResolver()有NotifyChange(URI,空)。
        返回Uri.parse(BASE_PATH +/+ ID);
    }    @覆盖
    公众诠释删除(URI URI,选择字符串,字符串[] selectionArgs两个){
        INT uriType = sURIMatcher.match(URI);
        SQLiteDatabase SQLDB = database.getWritableDatabase();
        INT rowsDeleted = 0;
        开关(uriType){
        案例TOTAL_ELEMENTS:
            rowsDeleted = sqlDB.delete(Consts.TABLE_WEBSITES_INFO,选择selectionArgs两个);
            打破;
        案例ELEMENT_ID:
            字符串ID = uri.getLastPathSegment();
            如果(TextUtils.isEmpty(选择)){
                rowsDeleted = sqlDB.delete(Consts.TABLE_WEBSITES_INFO,
                        Consts.COLUMN_ID +=+编号,
                        空值);
            }其他{
                rowsDeleted = sqlDB.delete(Consts.TABLE_WEBSITES_INFO,
                        Consts.COLUMN_ID +=+ ID +和+选择,
                        selectionArgs两个);
            }
            打破;
        默认:
            抛出新抛出:IllegalArgumentException(未知URI:+ URI);
        }        的getContext()getContentResolver()有NotifyChange(URI,空)。
        返回rowsDeleted;
    }    @覆盖
    公众诠释更新(开放的URI,ContentValues​​值,字符串的选择,
            的String [] selectionArgs两个){        INT uriType = sURIMatcher.match(URI);
        SQLiteDatabase SQLDB = database.getWritableDatabase();
        INT rowsUpdated = 0;
        开关(uriType){
        案例TOTAL_ELEMENTS:
            rowsUpdated = sqlDB.update(Consts.TABLE_WEBSITES_INFO,价值观,
                    选择selectionArgs两个);
            打破;
        案例ELEMENT_ID:
            字符串ID = uri.getLastPathSegment();
            如果(TextUtils.isEmpty(选择)){
                rowsUpdated = sqlDB.update(Consts.TABLE_WEBSITES_INFO,价值观,
                        Consts.COLUMN_ID +=+编号,
                        空值);
            }其他{
                rowsUpdated = sqlDB.update(Consts.TABLE_WEBSITES_INFO,价值观,
                        Consts.COLUMN_ID +=+ ID +和+选择,
                        selectionArgs两个);
            }
            打破;
        默认:
            抛出新抛出:IllegalArgumentException(未知URI:+ URI);
        }
        的getContext()getContentResolver()有NotifyChange(URI,空)。
        返回rowsUpdated;
    }    私人无效checkColumns(字符串[]投影){
        的String [] =可用{Consts.COLUMN_NAME,Consts.COLUMN_ID};
        如果(投影!= NULL){
            HashSet的<串GT; requestedColumns =新的HashSet<串GT;(Arrays.asList(投影));
            HashSet的<串GT; availableColumns =新的HashSet<串GT;(Arrays.asList(可用));
            //检查这些要求所有列可用
            如果(!availableColumns.containsAll(requestedColumns)){
                抛出新抛出:IllegalArgumentException(投影未知列);
            }
        }
    }    / *
     *键方法使用将数据从数据库LISTVIEW也使用
     *创建Matrix CURSOR传送回搜索查看
     * /
    私人光标buildSearchMatrixCursorFromStandardCursor(光标光标){        MatrixCursor cursorSearch =新MatrixCursor(SEARCH_SUGGEST_COLUMNS);
        INT标识= 0;
        INT指数= cursor.getColumnIndex(Consts.COLUMN_NAME);
        cursor.moveToFirst();
        而(!cursor.isAfterLast()){
            字符串名称= cursor.getString(指数);
            cursorSearch.addRow(新的String [] {
                    将String.valueOf(++ ID),
                    名称,
                    名称,
                    名称,
                    SearchManager.SUGGEST_NEVER_MAKE_SHORTCUT
            });
            cursor.moveToNext();        }        返回cursorSearch;
    }
}


解决方案

您正在使用的是ContentProvider的通用的,可用于搜索功能。

您可能会认为在第一次,也许你应该写专门的工作搜索ContentProvider的,但是:


  • 您将不得不重复很多code的。

  • ContentProviders没有设计具体,他们只是抽象的数据访问。

您搜索内容提供者将被用来做查询,您已经有与内容提供商有。

的的ContentProvider不需要特定于搜索。
另一方面,你的Adpater应当具体

  1. I have a ContentProvider that abstracts the info I'm using for a CursorAdapter to populate a list.

  2. I'm building a SearchView in the action bar and want to attach a search ContentProvider to it. Can I use the same provider for this? Is it good design? The SearchView content would be the same as in #1, it's just used to search a massive listview of items.

The ContentProvider code is below:

public class WebSitesContentProvider extends ContentProvider {

    // database
    private UserDatabaseHelper database;

    // Used for the UriMacher
    private static final int TOTAL_ELEMENTS = 10;
    private static final int ELEMENT_ID = 20;

    private static final String BASE_PATH = "websites";
    public static final Uri CONTENT_URI = Uri.parse("content://" + Consts.AUTHORITY + "/" + BASE_PATH);
    public static final String CONTENT_TYPE = ContentResolver.CURSOR_DIR_BASE_TYPE + "/website";
    public static final String CONTENT_ITEM_TYPE = ContentResolver.CURSOR_ITEM_BASE_TYPE + Consts.TABLE_WEBSITES_INFO;

    private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH);
    static {
        sURIMatcher.addURI(Consts.AUTHORITY, BASE_PATH, TOTAL_ELEMENTS);
        sURIMatcher.addURI(Consts.AUTHORITY, BASE_PATH + "/#", ELEMENT_ID);
    }

    @Override
    public boolean onCreate() {
        database = new UserDatabaseHelper(getContext());
        return false;
    }

    @Override
    public String getType(Uri uri) {
        return null;
    }

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

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

        // Check if the caller has requested a column which does not exists
        checkColumns(projection);

        // Set the table
        queryBuilder.setTables(Consts.TABLE_WEBSITES_INFO);

        int uriType = sURIMatcher.match(uri);
        switch (uriType) {
        case TOTAL_ELEMENTS:
            break;
        case ELEMENT_ID:
            // Adding the ID to the original query
            queryBuilder.appendWhere(Consts.COLUMN_ID + "=" + uri.getLastPathSegment());
            break;
        default:
            throw new IllegalArgumentException("Unknown URI: " + uri);
        }

        SQLiteDatabase db = database.getWritableDatabase();
        Cursor cursor = queryBuilder.query(db, projection, selection, selectionArgs, null, null, sortOrder);
        // Make sure that potential listeners are getting notified
        cursor.setNotificationUri(getContext().getContentResolver(), uri);

        return cursor;
    }

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        int uriType = sURIMatcher.match(uri);
        SQLiteDatabase sqlDB = database.getWritableDatabase();

        int rowsDeleted = 0;
        long id = 0;
        switch (uriType) {
        case TOTAL_ELEMENTS:
            id = sqlDB.insert(Consts.TABLE_WEBSITES_INFO, null, values);
            break;
        default:
            throw new IllegalArgumentException("Unknown URI: " + uri);
        }
        getContext().getContentResolver().notifyChange(uri, null);
        return Uri.parse(BASE_PATH + "/" + id);
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        int uriType = sURIMatcher.match(uri);
        SQLiteDatabase sqlDB = database.getWritableDatabase();
        int rowsDeleted = 0;
        switch (uriType) {
        case TOTAL_ELEMENTS:
            rowsDeleted = sqlDB.delete(Consts.TABLE_WEBSITES_INFO,
                    selection,
                    selectionArgs);
            break;
        case ELEMENT_ID:
            String id = uri.getLastPathSegment();
            if (TextUtils.isEmpty(selection)) {
                rowsDeleted = sqlDB.delete(Consts.TABLE_WEBSITES_INFO,
                        Consts.COLUMN_ID + "=" + id,
                        null);
            } else {
                rowsDeleted = sqlDB.delete(Consts.TABLE_WEBSITES_INFO,
                        Consts.COLUMN_ID + "=" + id + " and " + selection,
                        selectionArgs);
            }
            break;
        default:
            throw new IllegalArgumentException("Unknown URI: " + uri);
        }
        /*
         * Let's not notify content observers on deletes of less then 1 as each delete would cause a network call.
         * user could delete multiple entries at once. if the deletes are greater then 1 then it's probably a 
         * request to remove the entire list, this we will allow
         */
        //if(rowsDeleted>1)
            getContext().getContentResolver().notifyChange(uri, null);
        return rowsDeleted;
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {

        int uriType = sURIMatcher.match(uri);
        SQLiteDatabase sqlDB = database.getWritableDatabase();
        int rowsUpdated = 0;
        switch (uriType) {
        case TOTAL_ELEMENTS:
            rowsUpdated = sqlDB.update(Consts.TABLE_WEBSITES_INFO, 
                    values, 
                    selection,
                    selectionArgs);
            break;
        case ELEMENT_ID:
            String id = uri.getLastPathSegment();
            if (TextUtils.isEmpty(selection)) {
                rowsUpdated = sqlDB.update(Consts.TABLE_WEBSITES_INFO, 
                        values,
                        Consts.COLUMN_ID + "=" + id, 
                        null);
            } else {
                rowsUpdated = sqlDB.update(Consts.TABLE_WEBSITES_INFO, 
                        values,
                        Consts.COLUMN_ID + "=" + id + " and " + selection,
                        selectionArgs);
            }
            break;
        default:
            throw new IllegalArgumentException("Unknown URI: " + uri);
        }
        getContext().getContentResolver().notifyChange(uri, null);
        return rowsUpdated;
    }

    private void checkColumns(String[] projection) {
        String[] available = {
                Consts.COLUMN_USER,
                Consts.COLUMN_ID
        };
        if (projection != null) {
            HashSet<String> requestedColumns = new HashSet<String>(Arrays.asList(projection));
            HashSet<String> availableColumns = new HashSet<String>(Arrays.asList(available));
            // Check if all columns which are requested are available
            if (!availableColumns.containsAll(requestedColumns)) {
                throw new IllegalArgumentException("Unknown columns in projection");
            }
        }
    }
}

UPDATE

ContentProviders are generic and I agree on this. They can be adapted. So I adapted mine to handle SearchView data content.

Below is the entire ContentProvider acting as both a SearchView content provider and a ListView cursor adapter for anyone interested:

package org.jefferyemanuel.database;

import java.util.Arrays;
import java.util.HashSet;

import org.jefferyemanuel.bulkwebsites.Consts;
import org.jefferyemanuel.bulkwebsites.Utils;

import android.app.SearchManager;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.provider.BaseColumns;
import android.text.TextUtils;
import android.util.Log;

public class WebSitesContentProvider extends ContentProvider {

    /* define out search provider structures */
    // UriMatcher constant for search suggestions
    private static final int SEARCH_SUGGEST = 1;
    private static final String[] SEARCH_SUGGEST_COLUMNS = {
            BaseColumns._ID,
            SearchManager.SUGGEST_COLUMN_TEXT_1,
            SearchManager.SUGGEST_COLUMN_INTENT_DATA,
            SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA,
            SearchManager.SUGGEST_COLUMN_SHORTCUT_ID
    };

    // database
    private UserDatabaseHelper database;

    // Used for the UriMacher
    private static final int TOTAL_ELEMENTS = 10;
    private static final int ELEMENT_ID = 20;

    private static final String BASE_PATH = "websites";
    public static final Uri CONTENT_URI = Uri.parse("content://" + Consts.AUTHORITY + "/" + BASE_PATH);

    public static final String CONTENT_TYPE = ContentResolver.CURSOR_DIR_BASE_TYPE + "/website";
    public static final String CONTENT_ITEM_TYPE = ContentResolver.CURSOR_ITEM_BASE_TYPE + Consts.TABLE_WEBSITES_INFO;

    private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH);
    static {
        sURIMatcher.addURI(Consts.AUTHORITY, BASE_PATH, TOTAL_ELEMENTS);
        sURIMatcher.addURI(Consts.AUTHORITY, BASE_PATH + "/#", ELEMENT_ID);

        sURIMatcher.addURI(Consts.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, SEARCH_SUGGEST);
        sURIMatcher.addURI(Consts.AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", SEARCH_SUGGEST);
    }

    @Override
    public boolean onCreate() {
        database = new UserDatabaseHelper(getContext());
        return false;
    }

    @Override
    public String getType(Uri uri) {
        return null;
    }

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

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

        // Check if the caller has requested a column which does not exists
        checkColumns(projection);

        // Set the table
        queryBuilder.setTables(Consts.TABLE_WEBSITES_INFO);

        int uriType = sURIMatcher.match(uri);
        switch (uriType) {
        case TOTAL_ELEMENTS:
            break;

        case SEARCH_SUGGEST:
            queryBuilder.appendWhere(Consts.COLUMN_NAME + " LIKE '%" + uri.getLastPathSegment() + "%'");
            break;

        case ELEMENT_ID:
            // Adding the ID to the original query
            queryBuilder.appendWhere(Consts.COLUMN_ID + "=" + uri.getLastPathSegment());
            break;
        default:
            throw new IllegalArgumentException("Unknown URI: " + uri);
        }

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

        /*
         * If this request is from a SearchView then convert cursor to search Matrix cursor.
         */
        if (uriType == SEARCH_SUGGEST)
            cursor = buildSearchMatrixCursorFromStandardCursor(cursor);

        // Make sure that potential listeners are getting notified
        cursor.setNotificationUri(getContext().getContentResolver(), uri);

        return cursor;
    }

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        int uriType = sURIMatcher.match(uri);
        SQLiteDatabase sqlDB = database.getWritableDatabase();

        int rowsDeleted = 0;
        long id = 0;
        switch (uriType) {
        case TOTAL_ELEMENTS:
            id = sqlDB.insert(Consts.TABLE_WEBSITES_INFO, null, values);
            break;
        default:
            throw new IllegalArgumentException("Unknown URI: " + uri);
        }
        getContext().getContentResolver().notifyChange(uri, null);
        return Uri.parse(BASE_PATH + "/" + id);
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        int uriType = sURIMatcher.match(uri);
        SQLiteDatabase sqlDB = database.getWritableDatabase();
        int rowsDeleted = 0;
        switch (uriType) {
        case TOTAL_ELEMENTS:
            rowsDeleted = sqlDB.delete(Consts.TABLE_WEBSITES_INFO, selection, selectionArgs);
            break;
        case ELEMENT_ID:
            String id = uri.getLastPathSegment();
            if (TextUtils.isEmpty(selection)) {
                rowsDeleted = sqlDB.delete(Consts.TABLE_WEBSITES_INFO,
                        Consts.COLUMN_ID + "=" + id,
                        null);
            } else {
                rowsDeleted = sqlDB.delete(Consts.TABLE_WEBSITES_INFO,
                        Consts.COLUMN_ID + "=" + id + " and " + selection,
                        selectionArgs);
            }
            break;
        default:
            throw new IllegalArgumentException("Unknown URI: " + uri);
        }

        getContext().getContentResolver().notifyChange(uri, null);
        return rowsDeleted;
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection,
            String[] selectionArgs) {

        int uriType = sURIMatcher.match(uri);
        SQLiteDatabase sqlDB = database.getWritableDatabase();
        int rowsUpdated = 0;
        switch (uriType) {
        case TOTAL_ELEMENTS:
            rowsUpdated = sqlDB.update(Consts.TABLE_WEBSITES_INFO, values,
                    selection, selectionArgs);
            break;
        case ELEMENT_ID:
            String id = uri.getLastPathSegment();
            if (TextUtils.isEmpty(selection)) {
                rowsUpdated = sqlDB.update(Consts.TABLE_WEBSITES_INFO, values,
                        Consts.COLUMN_ID + "=" + id,
                        null);
            } else {
                rowsUpdated = sqlDB.update(Consts.TABLE_WEBSITES_INFO, values,
                        Consts.COLUMN_ID + "=" + id + " and " + selection,
                        selectionArgs);
            }
            break;
        default:
            throw new IllegalArgumentException("Unknown URI: " + uri);
        }
        getContext().getContentResolver().notifyChange(uri, null);
        return rowsUpdated;
    }

    private void checkColumns(String[] projection) {
        String[] available = { Consts.COLUMN_NAME, Consts.COLUMN_ID };
        if (projection != null) {
            HashSet<String> requestedColumns = new HashSet<String>(Arrays.asList(projection));
            HashSet<String> availableColumns = new HashSet<String>(Arrays.asList(available));
            // Check if all columns which are requested are available
            if (!availableColumns.containsAll(requestedColumns)) {
                throw new IllegalArgumentException("Unknown columns in projection");
            }
        }
    }

    /*
     * KEY METHOD THAT USES THE DATA FROM DATABASE THAT LISTVIEW ALSO USES 
     * TO CREATE A MATRIX CURSOR TO SEND BACK TO SEARCHVIEW
     */
    private Cursor buildSearchMatrixCursorFromStandardCursor(Cursor cursor) {

        MatrixCursor cursorSearch = new MatrixCursor(SEARCH_SUGGEST_COLUMNS);
        int id = 0;
        int index = cursor.getColumnIndex(Consts.COLUMN_NAME);
        cursor.moveToFirst();
        while (!cursor.isAfterLast()) {
            String name = cursor.getString(index);
            cursorSearch.addRow(new String[] {
                    String.valueOf(++id),
                    name,
                    name,
                    name,
                    SearchManager.SUGGEST_NEVER_MAKE_SHORTCUT
            });
            cursor.moveToNext();

        }

        return cursorSearch;
    }
}

解决方案

The ContentProvider you're using is generic and can be used for a search feature.

You may think at first that maybe you should write a ContentProvider that specifically works for search but:

  • You will have to duplicate a lot of code.
  • ContentProviders are not designed to be specific, they just abstract the access to data.

Your "Search Content Provider" will be used to make queries and you already have that with the Content Provider you have.

The ContentProvider doesn't need to be specific to search. On the other hand, your Adpater should be specific.

这篇关于Android的ContentProvider的双重目的:1.搜索提供商2.列出内容提供商的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆