1. 程式人生 > >Android四大元件——ContentProvider的增刪改查和優化

Android四大元件——ContentProvider的增刪改查和優化

前言

ContentProvider步驟:創資料庫,寫規則匹配,配置manifests,另一個應用使用

其實ContentProvider就是:在一個匹配器中寫入自己寫好的匹配規則,並對外提供寫好的匹配規則供使用,剩下的就是增刪改查的處理

細節處理:

在增刪改查中的查詢中,是沒有cursor.getBoolean這個方法的,所以要對資料庫中獲取布林值進行處理:

msg.setFlag(cursor.getInt(cursor.getColumnIndex("flag")) != 0);

ContentProvider的增刪改查

一、建立一個類繼承SQLiteOpenHelper,並用SQL語句建立一個SQLite
    public class CommonOpenHelper extends SQLiteOpenHelper {

    private static CommonOpenHelper helper;

    public static CommonOpenHelper getInstance(Context context) {
        if (helper == null) {
            helper = new CommonOpenHelper(context, "common.db", null, 1);
        }
        return helper;
    }

    private CommonOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("create table message(" +
                "id integer primary key autoincrement, " +
                "content varchar, " +
                "date varchar " +
                ")");
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }
}
二、建立一個類繼承ContentProvider,提供增刪改查的方法
    public class MyMessageProvider extends ContentProvider {

    //資料庫名
    public final static String DB_MESSAGE = "message";

    //放置一個數據庫
    CommonOpenHelper helper;
    SQLiteDatabase db;

    //空白匹配器
    UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);

    //自身的匹配規則
    final static int CODE_MESSAGE_INSERT = 0;
    final static int CODE_MESSAGE_QUERY = 1;
    final static int CODE_MESSAGE_DELETE = 2;
    final static int CODE_MESSAGE_UPDATE = 3;

    //主機名
    final static String authority = "com.handsome.nfcc";
    final static Uri BASE_URI = Uri.parse("content://com.handsome.nfcc");
    
    //寫入該主機名的匹配規則
    {
        matcher.addURI(authority, "message/insert", CODE_MESSAGE_INSERT);
        matcher.addURI(authority, "message/query", CODE_MESSAGE_QUERY);
        matcher.addURI(authority, "message/delete", CODE_MESSAGE_DELETE);
        matcher.addURI(authority, "message/update", CODE_MESSAGE_UPDATE);
    }

    //對外提供的URI
    public interface URI {
        Uri CODE_MESSAGE_INSERT = Uri.parse("content://" + authority + "/message/insert");
        Uri CODE_MESSAGE_QUERY = Uri.parse("content://" + authority + "/message/query");
        Uri CODE_MESSAGE_DELETE = Uri.parse("content://" + authority + "/message/delete");
        Uri CODE_MESSAGE_UPDATE = Uri.parse("content://" + authority + "/message/update");
    }

    @Override
    public boolean onCreate() {
        helper = CommonOpenHelper.getInstance(getContext());
        db = helper.getWritableDatabase();
        return false;
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
        switch (matcher.match(uri)) {
            case CODE_MESSAGE_QUERY:
                Cursor cursor = db.query(DB_MESSAGE, projection, selection, selectionArgs, null, null, sortOrder);
                //註冊內容觀察者,觀察資料變化
                cursor.setNotificationUri(getContext().getContentResolver(), BASE_URI);
                return cursor;
            default:
                throw new IllegalArgumentException("未識別的uri" + uri);
        }
    }

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

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        switch (matcher.match(uri)) {
            case CODE_MESSAGE_INSERT:
                long rowId = db.insert(DB_MESSAGE, null, values);
                if (rowId == -1) {
                    //新增失敗
                    return null;
                } else {
                    //傳送內容廣播
                    getContext().getContentResolver().notifyChange(BASE_URI, null);
                    //新增成功
                    return ContentUris.withAppendedId(uri, rowId);
                }
            default:
                throw new IllegalArgumentException("未識別的uri" + uri);
        }
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        switch (matcher.match(uri)) {
            case CODE_MESSAGE_DELETE:
                int number = db.delete(DB_MESSAGE, selection, selectionArgs);
                //傳送內容廣播
                getContext().getContentResolver().notifyChange(BASE_URI, null);
                return number;
            default:
                throw new IllegalArgumentException("未識別的uri" + uri);
        }
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
        switch (matcher.match(uri)) {
            case CODE_MESSAGE_UPDATE:
                int number = db.update(DB_MESSAGE, values, selection, selectionArgs);
                //傳送內容廣播
                getContext().getContentResolver().notifyChange(BASE_URI, null);
                return number;
            default:
                throw new IllegalArgumentException("未識別的uri" + uri);
        }
    }
}
三、在manifests檔案中配置你所寫的ContentProvider
    <provider
            android:name=".Provider.MyMessageProvider"
            android:authorities="com.handsome.nfcc" />
四、在另一個應用中寫一個數據庫的增刪改查類,使用該ContentProvider
    public class MessageDao {

    /**
     * 新增資料
     */
    public static boolean insert(ContentResolver resolver, Message msg) {
        ContentValues values = new ContentValues();
        values.put("content", msg.getContent());
        values.put("date", DateUtils.showDate());
        resolver.insert(MyMessageProvider.URI.CODE_MESSAGE_INSERT, values);
        return true;
    }


    /**
     * 刪除資料
     */
    public static void delete(ContentResolver resolver, int id) {
        resolver.delete(MyMessageProvider.URI.CODE_MESSAGE_DELETE, "id = " + id, null);
    }

    /**
     * 刪除全部資料
     */
    public static void deleteAll(ContentResolver resolver) {
        resolver.delete(MyMessageProvider.URI.CODE_MESSAGE_DELETE, null, null);
    }

    /**
     * 查詢資料
     *
     * @param resolver
     * @return
     */
    public static List<Message> query(ContentResolver resolver) {
        List<Message> list = new ArrayList<>();
        Cursor cursor = resolver.query(MyMessageProvider.URI.CODE_MESSAGE_QUERY, null, null, null, null);
        while (cursor.moveToNext()) {
            Message msg = new Message();
            msg.setDate(cursor.getString(cursor.getColumnIndex("date")));
            msg.setContent(cursor.getString(cursor.getColumnIndex("content")));
            msg.setId(cursor.getInt(cursor.getColumnIndex("id")));
            list.add(0, msg);
        }
        return list;
    }


}

ContentProvider的優化

往往在一個專案中有很多的資料庫,這個時候並不是重複的寫ContentProvider程式碼,而是將所有資料庫中放在一個ContentProvider中,提供一個查詢表名的方法,並對其相應的表進行操作

一、ContentProvider的程式碼優化(一套程式碼適用多個數據庫)

public class MyDataProvider extends ContentProvider {

    //資料庫名
    public final static String DB_DATA = "data";
    public final static String DB_FETCH = "fetch";
    public final static String DB_MESSAGE = "message";

    //放置一個數據庫
    CommonOpenHelper helper;
    SQLiteDatabase db;

    UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);

    //自身的匹配規則
    final static int CODE_DATA = 0;
    final static int CODE_FETCH = 1;
    final static int CODE_MESSAGE = 2;

    //主機名
    final static String authority = "com.handsome.nfc";
    final static Uri BASE_URI = Uri.parse("content://com.handsome.nfc");


    //寫入該主機名的匹配規則
    {
        matcher.addURI(authority, "data", CODE_DATA);
        matcher.addURI(authority, "fetch", CODE_FETCH);
        matcher.addURI(authority, "message", CODE_MESSAGE);
    }

    //對外提供的URI
    public interface URI {
        Uri DATA_CONTENT_URI = Uri.parse(BASE_URI + "/data");
        Uri FETCH_CONTENT_URI = Uri.parse(BASE_URI + "/fetch");
        Uri MESSAGE_CONTENT_URI = Uri.parse(BASE_URI + "/message");
    }

    /**
     * 獲取資料庫表名
     *
     * @param uri
     * @return
     */
    private String getTableName(Uri uri) {
        String tableName = null;
        switch (matcher.match(uri)) {
            case CODE_DATA:
                tableName = DB_DATA;
                break;
            case CODE_FETCH:
                tableName = DB_FETCH;
                break;
            case CODE_MESSAGE:
                tableName = DB_MESSAGE;
                break;
            default:
                break;
        }
        return tableName;
    }

    @Override
    public boolean onCreate() {
        helper = CommonOpenHelper.getInstance(getContext());
        db = helper.getWritableDatabase();
        return false;
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
        String tableName = getTableName(uri);
        if (tableName == null) {
            throw new IllegalArgumentException("非法Uri:" + uri);
        }
        Cursor cursor = db.query(tableName, projection, selection, selectionArgs, null, null, sortOrder);
        //註冊內容觀察者,觀察資料變化
        cursor.setNotificationUri(getContext().getContentResolver(), BASE_URI);
        return cursor;
    }

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

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        String tableName = getTableName(uri);
        if (tableName == null) {
            throw new IllegalArgumentException("非法Uri:" + uri);
        }
        long rowId = db.insert(tableName, null, values);
        if (rowId == -1) {
            return null;
        } else {
            //傳送內容廣播
            getContext().getContentResolver().notifyChange(BASE_URI, null);
            return ContentUris.withAppendedId(uri, rowId);
        }
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        String tableName = getTableName(uri);
        if (tableName == null) {
            throw new IllegalArgumentException("非法Uri:" + uri);
        }
        int number = db.delete(tableName, selection, selectionArgs);
        //傳送內容廣播
        getContext().getContentResolver().notifyChange(BASE_URI, null);
        return number;
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
        String tableName = getTableName(uri);
        if (tableName == null) {
            throw new IllegalArgumentException("非法Uri:" + uri);
        }
        int number = db.update(tableName, values, selection, selectionArgs);
        //傳送內容廣播
        getContext().getContentResolver().notifyChange(BASE_URI, null);
        return number;
    }
}

二、在各個不同的資料庫中的使用

Data資料庫通過名字查詢示例

private static boolean queryDataByName(ContentResolver resolver, String tag_id) {
        Cursor cursor = resolver.query(MyDataProvider.URI.DATA_CONTENT_URI, null, "tag_id = '" + tag_id + "'", null, null);
        if (cursor.moveToFirst()) {
            return true;
        }
        return false;
    }
Fetch資料庫插入示例
public static boolean insert(ContentResolver resolver, Fetch fetch) {
        ContentValues values = new ContentValues();
        values.put("fetch_num", fetch.getFetch_num());
        values.put("username", fetch.getUsername());
        values.put("installationId", fetch.getInstallationId());
        values.put("created", fetch.getCreated());
        values.put("date", System.currentTimeMillis());
        resolver.insert(MyDataProvider.URI.FETCH_CONTENT_URI, values);
        return true;
    }
Message資料庫查詢示例
 public static List<Message> query(ContentResolver resolver) {
        List<Message> list = new ArrayList<>();
        Cursor cursor = resolver.query(MyDataProvider.URI.MESSAGE_CONTENT_URI, null, null, null, null);
        while (cursor.moveToNext()) {
            Message msg = new Message();
            msg.setDate(cursor.getString(cursor.getColumnIndex("date")));
            msg.setContent(cursor.getString(cursor.getColumnIndex("content")));
            msg.setId(cursor.getInt(cursor.getColumnIndex("id")));
            list.add(0, msg);
        }
        return list;
    }