Android ContentProvider的双重用途:1。搜索提供商和2.列出内容提供商

时间:2013-09-05 20:29:54

标签: android search android-contentprovider searchview

  1. 我有ContentProvider摘要我正在使用CursorAdapter填充列表的信息。

  2. 我正在操作栏中构建SearchView,并希望为其附加搜索ContentProvider。我可以使用相同的提供商吗?这是好的设计吗? SearchView内容与#1中的相同,只是用于搜索项目的大量列表视图。

  3. ContentProvider代码如下:

    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");
                }
            }
        }
    }
    

    更新

    ContentProvider是通用的,我同意这一点。 他们可以适应。 所以我调整了我的处理SearchView数据内容。

    以下是整个ContentProvider充当SearchView内容提供商和ListView游标适配器,适合所有感兴趣的人:

    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;
        }
    }
    

1 个答案:

答案 0 :(得分:0)

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

您可能首先想到,您可能应该编写一个专门用于搜索的ContentProvider,但是:

  • 你必须复制很多代码。
  • ContentProviders并非专门设计,它们只是抽象了对数据的访问。

您的“搜索内容提供商”将用于进行查询,您已经拥有了内容提供商。

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