android 玩转ContentProvider之一--实现ContentProvider操作数据库

来源:互联网 发布:windows最新更新 编辑:程序博客网 时间:2024/05/20 13:19

本人原创作品,谢绝转载!

作为android四大组件之一,今天总结一下它的用法。

ContentProvider官方有很多地方提到,其中一个是在API文档上(http://developer.android.com/guide/topics/providers/content-providers.html)面有介绍,有兴趣去看一下,虽然是英文的,对了解ContentProvider很有用;还有一个地方是android SDK中的%android_home%/samples/android-x/下面的一个NotePad的demo,代码架构可以参考该demo。本文来自此demo,并做相关修改。

代码:

SQLite数据库直接操作类:

DatabaseHelper.java

package com.jacp.database;import android.content.Context;import android.database.sqlite.SQLiteDatabase;import android.database.sqlite.SQLiteOpenHelper;import com.jacp.demo.provider.Provider;/** * 操作数据库 * @author jacp * */public class DatabaseHelper extends SQLiteOpenHelper {private static final String DATABASE_NAME = "jacp_demo.db";private static final int DATABASE_VERSION = 1;    public DatabaseHelper(Context context) {        super(context, DATABASE_NAME, null, DATABASE_VERSION);    }    @Override    public void onCreate(SQLiteDatabase db) {        db.execSQL("CREATE TABLE " + Provider.PersonColumns.TABLE_NAME + " ("                + Provider.PersonColumns._ID + " INTEGER PRIMARY KEY,"                + Provider.PersonColumns.NAME + " TEXT,"                + Provider.PersonColumns.AGE + " INTEGER"                + ");");    }    @Override    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {        db.execSQL("DROP TABLE IF EXISTS " + Provider.PersonColumns.TABLE_NAME);        onCreate(db);    }}
保存跟数据库及表有关的常量:
Provider.java

package com.jacp.demo.provider;import android.net.Uri;import android.provider.BaseColumns;/** * 存放跟数据库有关的常量 * @author jacp * */public class Provider {// 这个是每个Provider的标识,在Manifest中使用public static final String AUTHORITY = "com.jacp.provider.demo.person";    public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.jacp.demo";    public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.jacp.demo";    /**     * 跟Person表相关的常量     * @author jacp     *     */public static final class PersonColumns implements BaseColumns {// CONTENT_URI跟数据库的表关联,最后根据CONTENT_URI来查询对应的表public static final Uri CONTENT_URI = Uri.parse("content://"+ AUTHORITY +"/persons");public static final String TABLE_NAME = "person";public static final String DEFAULT_SORT_ORDER = "age desc";public static final String NAME = "name";public static final String AGE = "age";}}

对数据增删改查操作的类:

PersonProvider.java

package com.jacp.demo.provider;import java.util.HashMap;import android.content.ContentProvider;import android.content.ContentUris;import android.content.ContentValues;import android.content.UriMatcher;import android.database.Cursor;import android.database.SQLException;import android.database.sqlite.SQLiteDatabase;import android.database.sqlite.SQLiteQueryBuilder;import android.net.Uri;import android.text.TextUtils;import com.jacp.database.DatabaseHelper;/** * 操作数据库Person表的ContentProvider * @author jacp * */public class PersonProvider extends ContentProvider {    private static HashMap<String, String> sPersonsProjectionMap;    private static final int PERSONS = 1;    private static final int PERSONS_ID = 2;    private static final UriMatcher sUriMatcher;    private DatabaseHelper mOpenHelper;    @Override    public boolean onCreate() {        mOpenHelper = new DatabaseHelper(getContext());        return true;    }    @Override    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,            String sortOrder) {        SQLiteQueryBuilder qb = new SQLiteQueryBuilder();        qb.setTables(Provider.PersonColumns.TABLE_NAME);        switch (sUriMatcher.match(uri)) {        case PERSONS:            qb.setProjectionMap(sPersonsProjectionMap);            break;        case PERSONS_ID:            qb.setProjectionMap(sPersonsProjectionMap);            qb.appendWhere(Provider.PersonColumns._ID + "=" + uri.getPathSegments().get(1));            break;        default:            throw new IllegalArgumentException("Unknown URI " + uri);        }        // If no sort order is specified use the default        String orderBy;        if (TextUtils.isEmpty(sortOrder)) {            orderBy = Provider.PersonColumns.DEFAULT_SORT_ORDER;        } else {            orderBy = sortOrder;        }        // Get the database and run the query        SQLiteDatabase db = mOpenHelper.getReadableDatabase();        Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, orderBy);        // Tell the cursor what uri to watch, so it knows when its source data changes        c.setNotificationUri(getContext().getContentResolver(), uri);        return c;    }    @Override    public String getType(Uri uri) {        switch (sUriMatcher.match(uri)) {        case PERSONS:            return Provider.CONTENT_TYPE;        case PERSONS_ID:            return Provider.CONTENT_ITEM_TYPE;        default:            throw new IllegalArgumentException("Unknown URI " + uri);        }    }    @Override    public Uri insert(Uri uri, ContentValues initialValues) {        // Validate the requested uri        if (sUriMatcher.match(uri) != PERSONS) {            throw new IllegalArgumentException("Unknown URI " + uri);        }        ContentValues values;        if (initialValues != null) {            values = new ContentValues(initialValues);        } else {            values = new ContentValues();        }        // Make sure that the fields are all set        if (values.containsKey(Provider.PersonColumns.NAME) == false) {            values.put(Provider.PersonColumns.NAME, "");        }        if (values.containsKey(Provider.PersonColumns.AGE) == false) {            values.put(Provider.PersonColumns.AGE, 0);        }        SQLiteDatabase db = mOpenHelper.getWritableDatabase();        long rowId = db.insert(Provider.PersonColumns.TABLE_NAME, Provider.PersonColumns.NAME, values);        if (rowId > 0) {            Uri noteUri = ContentUris.withAppendedId(Provider.PersonColumns.CONTENT_URI, rowId);            getContext().getContentResolver().notifyChange(noteUri, null);            return noteUri;        }        throw new SQLException("Failed to insert row into " + uri);    }    @Override    public int delete(Uri uri, String where, String[] whereArgs) {        SQLiteDatabase db = mOpenHelper.getWritableDatabase();        int count;        switch (sUriMatcher.match(uri)) {        case PERSONS:            count = db.delete(Provider.PersonColumns.TABLE_NAME, where, whereArgs);            break;        case PERSONS_ID:            String noteId = uri.getPathSegments().get(1);            count = db.delete(Provider.PersonColumns.TABLE_NAME, Provider.PersonColumns._ID + "=" + noteId                    + (!TextUtils.isEmpty(where) ? " AND (" + where + ')' : ""), whereArgs);            break;        default:            throw new IllegalArgumentException("Unknown URI " + uri);        }        getContext().getContentResolver().notifyChange(uri, null);        return count;    }    @Override    public int update(Uri uri, ContentValues values, String where, String[] whereArgs) {        SQLiteDatabase db = mOpenHelper.getWritableDatabase();        int count;        switch (sUriMatcher.match(uri)) {        case PERSONS:            count = db.update(Provider.PersonColumns.TABLE_NAME, values, where, whereArgs);            break;        case PERSONS_ID:            String noteId = uri.getPathSegments().get(1);            count = db.update(Provider.PersonColumns.TABLE_NAME, values, Provider.PersonColumns._ID + "=" + noteId                    + (!TextUtils.isEmpty(where) ? " AND (" + where + ')' : ""), whereArgs);            break;        default:            throw new IllegalArgumentException("Unknown URI " + uri);        }        getContext().getContentResolver().notifyChange(uri, null);        return count;    }    static {        sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);        // 这个地方的persons要和PersonColumns.CONTENT_URI中最后面的一个Segment一致        sUriMatcher.addURI(Provider.AUTHORITY, "persons", PERSONS);        sUriMatcher.addURI(Provider.AUTHORITY, "persons/#", PERSONS_ID);        sPersonsProjectionMap = new HashMap<String, String>();        sPersonsProjectionMap.put(Provider.PersonColumns._ID, Provider.PersonColumns._ID);        sPersonsProjectionMap.put(Provider.PersonColumns.NAME, Provider.PersonColumns.NAME);        sPersonsProjectionMap.put(Provider.PersonColumns.AGE, Provider.PersonColumns.AGE);    }}


表对应的数据对象:
Person.java

package com.jacp.pojos;public class Person {public String name;public int age;}


Activity测试:
ContentProviderDemoActivity.java

package com.jacp.demo;import android.app.Activity;import android.content.ContentValues;import android.database.Cursor;import android.net.Uri;import android.os.Bundle;import android.text.TextUtils;import android.util.Log;import com.jacp.demo.provider.Provider;import com.jacp.pojos.Person;public class ContentProviderDemoActivity extends Activity {private static final String TAG = "ProviderActivity";    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);                test();    }        private void test() {    Person p = new Person();        p.name = "jacp";        p.age = 99;        int id = insert(p);        query(id);    }        private int insert(Person person) {    ContentValues values = new ContentValues();    values.put(Provider.PersonColumns.NAME, person.name);    values.put(Provider.PersonColumns.AGE, person.age);    Uri uri = getContentResolver().insert(Provider.PersonColumns.CONTENT_URI, values);    Log.i(TAG, "insert uri="+uri);    String lastPath = uri.getLastPathSegment();    if (TextUtils.isEmpty(lastPath)) {    Log.i(TAG, "insert failure!");    } else {    Log.i(TAG, "insert success! the id is " + lastPath);    }        return Integer.parseInt(lastPath);    }        private void query(int id) {    Cursor c = getContentResolver().query(Provider.PersonColumns.CONTENT_URI, new String[] { Provider.PersonColumns.NAME, Provider.PersonColumns.AGE }, Provider.PersonColumns._ID + "=?", new String[] { id + "" }, null);    if (c != null && c.moveToFirst()) {    Person p = new Person();    p.name = c.getString(c.getColumnIndexOrThrow(Provider.PersonColumns.NAME));    p.age = c.getInt(c.getColumnIndexOrThrow(Provider.PersonColumns.AGE));    Log.i(TAG, "person.name="+p.name+"---person.age="+p.age);    } else {    Log.i(TAG, "query failure!");    }    }}

Manifest.xml文件中注册配置:

<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.jacp.demo"    android:versionCode="1"    android:versionName="1.0" >    <uses-sdk android:minSdkVersion="8" />    <application        android:icon="@drawable/ic_launcher"        android:label="@string/app_name" >        <activity            android:label="@string/app_name"            android:name=".ContentProviderDemoActivity" >            <intent-filter >                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity>                <!-- 注意这个地方的位置,是在application标签里面;android:authorities对应Provider.AUTHORITY -->        <provider android:name=".provider.PersonProvider"            android:authorities="com.jacp.provider.demo.person" />            </application></manifest>

如果对ContentProvider不熟悉,把SDK中的NotePad项目copy改几遍,在改的时候就会明白每个地方起的作用,copy改了几次就会慢慢熟悉了。

demo下载地址:http://download.csdn.net/detail/maylian7700/4150144


如有遗漏不当之处,欢迎批评指正!
原创粉丝点击