Android数据存储之ContentProvider基本原理

对于ContentProvider,一般的使用方法是在主Activity中使用ContentResolver调用增删改查的方法去调用在ContentProvider中对应的增删改查的方法,而在ContentProvider的中通过SQLiteOpenHelper获得目标应用的可写的数据库,然后在对应的增删改查方法中对数据库进行实际操作。在此之前为了之后的操作方便先定义一个元数据接口声明各项要用到的常量,比如库表名称,URI,mime类型等

元数据代码:

 1 public interface DatabaseMetaData {
 2     
 3     // uri : content://com.example.mycontentprovider
 4     public static final String AUTHORITY = "com.example.contentprovideractivity.mycontentprovider";
 5     
 6     public static final String DATABASE_NAME = "SHUAI";
 7     
 8     public static final int VERSION = 1;
 9     
10     public static interface MemberTableMetaData extends BaseColumns {
11          
12         public static final String TABLE_NAME = "member";
13         // 外部程序访问本表所需的URI
14         public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" + TABLE_NAME);
15         // 取得表中全部信息
16         public static final String CONTACT_LIST = "vnd.android.cursor.dir/vnd.mycontentprovider.member";
17         // 取得表中一项信息,按 id查询
18         public static final String CONTACT_ITEM = "vnd.android.cursor.item/vnd.mycontentprovider.member";
19         
20         public static final String MEMBER_NAME = "name";
21         public static final String MEMBER_TELEPHONE = "telephone";
22         // 排序操作
23         public static final String SORT_ORDER = "_id DESC";
24     }
25 }

然后准备好SQLiteOpenHelper

 1 public class DatabaseOpenHelper extends SQLiteOpenHelper {
 2 
 3     public DatabaseOpenHelper(Context context) {
 4         super(context, DatabaseMetaData.DATABASE_NAME, null,
 5                 DatabaseMetaData.VERSION);
 6     }
 7 
 8     @Override
 9     public void onCreate(SQLiteDatabase db) {
10 
11         String sql = "CREATE TABLE "
12                 + DatabaseMetaData.MemberTableMetaData.TABLE_NAME + " ( " 
13                 + DatabaseMetaData.MemberTableMetaData._ID              + " INTEGER PRIMARY KEY ,"
14                 + DatabaseMetaData.MemberTableMetaData.MEMBER_NAME      + " VARCHAR(50) NOT NULL ," 
15                 + DatabaseMetaData.MemberTableMetaData.MEMBER_TELEPHONE + " VARCHAR(50) NOT NULL" 
16                 + " )";
17         db.execSQL(sql);
18     }
19 
20     @Override
21     public void onUpgrade(SQLiteDatabase db, int oldVerson, int newVersion) {
22         
23         String sql = "DROP TABLE IF EXISTS " + DatabaseMetaData.MemberTableMetaData.TABLE_NAME;
24         db.execSQL(sql);
25     }
26 
27 }

而在ContentProvider中,需要一个UriMatcher来判断传递的URI有没有id项,因为使用ContentResolver需要传入一个URI,若URI中有id项,如 content://AUTHORITY/TABLE_NAME/ID 则操作类型为vnd.android.cursor.item单项操作;否则为vnd.android.cursor.dir是多项操作

public class MyContentProvider extends ContentProvider {

    private static UriMatcher matcher = null;
    private static final int GET_MEMBER_LIST = 1;
    private static final int GET_MEMBER_ITEM = 2;
    
    static {
        matcher = new UriMatcher(UriMatcher.NO_MATCH);
        matcher.addURI(DatabaseMetaData.AUTHORITY, DatabaseMetaData.MemberTableMetaData.TABLE_NAME, GET_MEMBER_LIST);
        matcher.addURI(DatabaseMetaData.AUTHORITY, DatabaseMetaData.MemberTableMetaData.TABLE_NAME + "/#", GET_MEMBER_ITEM);
    
    }

启动ContentProvider时需要初始化DatabaseOpenHelper

    private DatabaseOpenHelper helper = null;
    
    @Override
    public boolean onCreate() {
        helper = new DatabaseOpenHelper(super.getContext());
        return true;
    }

用插入数据举例,复写insert() 方法

 1     @Override
 2     public Uri insert(Uri uri, ContentValues values) {
 3         System.out.println(" ***** = " + uri);
 4         
 5         // 获得可写数据库
 6         SQLiteDatabase db = helper.getWritableDatabase();
 7         long insertId = 0;
 8         
 9         switch(this.matcher.match(uri)) {
10         
11         case GET_MEMBER_LIST:
12             //执行插入操作
13             insertId = db.insert(DatabaseMetaData.MemberTableMetaData.TABLE_NAME, DatabaseMetaData.MemberTableMetaData._ID, values);
14             System.out.println("insert id = " + insertId);
15             String path = uri.toString() + "/" + insertId;
16             return Uri.parse(path);
17         case GET_MEMBER_ITEM:
18             return null;
19         default:
20             throw new UnsupportedOperationException("Not Support Operation :"
21                     + uri);
22         }
23     }

而ContentResolver端通过ContentVaules键值对来传送数据

 1    private long insertTest(String name, String telephone) {
 2         // 客户端调用ContentResolver
 3         ContentResolver resolver = super.getContentResolver();
 4         ContentValues values = new ContentValues();
 5         values.put(DatabaseMetaData.MemberTableMetaData.MEMBER_NAME, name);
 6         values.put(DatabaseMetaData.MemberTableMetaData.MEMBER_TELEPHONE, telephone);
 7         
 8         Uri resultUri = resolver.insert(DatabaseMetaData.MemberTableMetaData.CONTENT_URI, values);
 9         System.out.println("### " + resultUri  );
10         
11         return ContentUris.parseId(resultUri);
12     }

这样就完成了一次客户端向目的应用数据库插入数据的操作,但是大多数时候我们用的是系统的ContentProvider,只需操作客户端的ContentResolver,上述代码只是为了更好的理解ContentProvider的工作原理

原文地址:https://www.cnblogs.com/moka/p/3060708.html