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


我的理解:ConetntRolver(用户使用入口)---------->ContentProvider(提供统一操作数据库的入口)-------->SqlIteHelper操作数据库

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

作为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数据库直接操作类:

  1. DatabaseHelper.java  
  1. package com.jacp.database;  
  2.   
  3. import android.content.Context;  
  4. import android.database.sqlite.SQLiteDatabase;  
  5. import android.database.sqlite.SQLiteOpenHelper;  
  6.   
  7. import com.jacp.demo.provider.Provider;  
  8.   
  9. /** 
  10.  * 操作数据库 
  11.  * @author jacp 
  12.  * 
  13.  */  
  14. public class DatabaseHelper extends SQLiteOpenHelper {  
  15.     private static final String DATABASE_NAME = "jacp_demo.db";  
  16.     private static final int DATABASE_VERSION = 1;  
  17.   
  18.     public DatabaseHelper(Context context) {  
  19.         super(context, DATABASE_NAME, null, DATABASE_VERSION);  
  20.     }  
  21.   
  22.     @Override  
  23.     public void onCreate(SQLiteDatabase db) {  
  24.         db.execSQL("CREATE TABLE " + Provider.PersonColumns.TABLE_NAME + " ("  
  25.                 + Provider.PersonColumns._ID + " INTEGER PRIMARY KEY,"  
  26.                 + Provider.PersonColumns.NAME + " TEXT,"  
  27.                 + Provider.PersonColumns.AGE + " INTEGER"  
  28.                 + ");");  
  29.     }  
  30.   
  31.     @Override  
  32.     public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {  
  33.         db.execSQL("DROP TABLE IF EXISTS " + Provider.PersonColumns.TABLE_NAME);  
  34.         onCreate(db);  
  35.     }  
  36. }  
保存跟数据库及表有关的常量:
Provider.java
  1. package com.jacp.demo.provider;  
  2.   
  3. import android.net.Uri;  
  4. import android.provider.BaseColumns;  
  5.   
  6. /** 
  7.  * 存放跟数据库有关的常量 
  8.  * @author jacp 
  9.  * 
  10.  */  
  11. public class Provider {  
  12.       
  13.     // 这个是每个Provider的标识,在Manifest中使用  
  14.     public static final String AUTHORITY = "com.jacp.provider.demo.person";  
  15.       
  16.     public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.jacp.demo";  
  17.   
  18.     public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.jacp.demo";  
  19.   
  20.     /** 
  21.      * 跟Person表相关的常量 
  22.      * @author jacp 
  23.      * 
  24.      */  
  25.     public static final class PersonColumns implements BaseColumns {  
  26.         // CONTENT_URI跟数据库的表关联,最后根据CONTENT_URI来查询对应的表  
  27.         public static final Uri CONTENT_URI = Uri.parse("content://"+ AUTHORITY +"/persons");  
  28.         public static final String TABLE_NAME = "person";  
  29.         public static final String DEFAULT_SORT_ORDER = "age desc";  
  30.           
  31.         public static final String NAME = "name";  
  32.         public static final String AGE = "age";  
  33.           
  34.     }  
  35.       
  36. }  

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

PersonProvider.java
  1. package com.jacp.demo.provider;  
  2.   
  3. import java.util.HashMap;  
  4.   
  5. import android.content.ContentProvider;  
  6. import android.content.ContentUris;  
  7. import android.content.ContentValues;  
  8. import android.content.UriMatcher;  
  9. import android.database.Cursor;  
  10. import android.database.SQLException;  
  11. import android.database.sqlite.SQLiteDatabase;  
  12. import android.database.sqlite.SQLiteQueryBuilder;  
  13. import android.net.Uri;  
  14. import android.text.TextUtils;  
  15.   
  16. import com.jacp.database.DatabaseHelper;  
  17.   
  18. /** 
  19.  * 操作数据库Person表的ContentProvider 
  20.  * @author jacp 
  21.  * 
  22.  */  
  23. public class PersonProvider extends ContentProvider {  
  24.   
  25.     private static HashMap<String, String> sPersonsProjectionMap;  
  26.   
  27.     private static final int PERSONS = 1;  
  28.     private static final int PERSONS_ID = 2;  
  29.   
  30.     private static final UriMatcher sUriMatcher;  
  31.   
  32.     private DatabaseHelper mOpenHelper;  
  33.   
  34.     @Override  
  35.     public boolean onCreate() {  
  36.         mOpenHelper = new DatabaseHelper(getContext());  
  37.         return true;  
  38.     }  
  39.   
  40.     @Override  
  41.     public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,  
  42.             String sortOrder) {  
  43.         SQLiteQueryBuilder qb = new SQLiteQueryBuilder();  
  44.         qb.setTables(Provider.PersonColumns.TABLE_NAME);  
  45.   
  46.         switch (sUriMatcher.match(uri)) {  
  47.         case PERSONS:  
  48.             qb.setProjectionMap(sPersonsProjectionMap);  
  49.             break;  
  50.   
  51.         case PERSONS_ID:  
  52.             qb.setProjectionMap(sPersonsProjectionMap);  
  53.             qb.appendWhere(Provider.PersonColumns._ID + "=" + uri.getPathSegments().get(1));  
  54.             break;  
  55.   
  56.         default:  
  57.             throw new IllegalArgumentException("Unknown URI " + uri);  
  58.         }  
  59.   
  60.         // If no sort order is specified use the default  
  61.         String orderBy;  
  62.         if (TextUtils.isEmpty(sortOrder)) {  
  63.             orderBy = Provider.PersonColumns.DEFAULT_SORT_ORDER;  
  64.         } else {  
  65.             orderBy = sortOrder;  
  66.         }  
  67.   
  68.         // Get the database and run the query  
  69.         SQLiteDatabase db = mOpenHelper.getReadableDatabase();  
  70.         Cursor c = qb.query(db, projection, selection, selectionArgs, nullnull, orderBy);  
  71.   
  72.         // Tell the cursor what uri to watch, so it knows when its source data changes  
  73.         c.setNotificationUri(getContext().getContentResolver(), uri);  
  74.         return c;  
  75.     }  
  76.   
  77.     @Override  
  78.     public String getType(Uri uri) {  
  79.         switch (sUriMatcher.match(uri)) {  
  80.         case PERSONS:  
  81.             return Provider.CONTENT_TYPE;  
  82.         case PERSONS_ID:  
  83.             return Provider.CONTENT_ITEM_TYPE;  
  84.         default:  
  85.             throw new IllegalArgumentException("Unknown URI " + uri);  
  86.         }  
  87.     }  
  88.   
  89.     @Override  
  90.     public Uri insert(Uri uri, ContentValues initialValues) {  
  91.         // Validate the requested uri  
  92.         if (sUriMatcher.match(uri) != PERSONS) {  
  93.             throw new IllegalArgumentException("Unknown URI " + uri);  
  94.         }  
  95.   
  96.         ContentValues values;  
  97.         if (initialValues != null) {  
  98.             values = new ContentValues(initialValues);  
  99.         } else {  
  100.             values = new ContentValues();  
  101.         }  
  102.   
  103.         // Make sure that the fields are all set  
  104.         if (values.containsKey(Provider.PersonColumns.NAME) == false) {  
  105.             values.put(Provider.PersonColumns.NAME, "");  
  106.         }  
  107.   
  108.         if (values.containsKey(Provider.PersonColumns.AGE) == false) {  
  109.             values.put(Provider.PersonColumns.AGE, 0);  
  110.         }  
  111.   
  112.         SQLiteDatabase db = mOpenHelper.getWritableDatabase();  
  113.         long rowId = db.insert(Provider.PersonColumns.TABLE_NAME, Provider.PersonColumns.NAME, values);  
  114.         if (rowId > 0) {  
  115.             Uri noteUri = ContentUris.withAppendedId(Provider.PersonColumns.CONTENT_URI, rowId);  
  116.             getContext().getContentResolver().notifyChange(noteUri, null);  
  117.             return noteUri;  
  118.         }  
  119.   
  120.         throw new SQLException("Failed to insert row into " + uri);  
  121.     }  
  122.   
  123.     @Override  
  124.     public int delete(Uri uri, String where, String[] whereArgs) {  
  125.         SQLiteDatabase db = mOpenHelper.getWritableDatabase();  
  126.         int count;  
  127.         switch (sUriMatcher.match(uri)) {  
  128.         case PERSONS:  
  129.             count = db.delete(Provider.PersonColumns.TABLE_NAME, where, whereArgs);  
  130.             break;  
  131.   
  132.         case PERSONS_ID:  
  133.             String noteId = uri.getPathSegments().get(1);  
  134.             count = db.delete(Provider.PersonColumns.TABLE_NAME, Provider.PersonColumns._ID + "=" + noteId  
  135.                     + (!TextUtils.isEmpty(where) ? " AND (" + where + ')' : ""), whereArgs);  
  136.             break;  
  137.   
  138.         default:  
  139.             throw new IllegalArgumentException("Unknown URI " + uri);  
  140.         }  
  141.   
  142.         getContext().getContentResolver().notifyChange(uri, null);  
  143.         return count;  
  144.     }  
  145.   
  146.     @Override  
  147.     public int update(Uri uri, ContentValues values, String where, String[] whereArgs) {  
  148.         SQLiteDatabase db = mOpenHelper.getWritableDatabase();  
  149.         int count;  
  150.         switch (sUriMatcher.match(uri)) {  
  151.         case PERSONS:  
  152.             count = db.update(Provider.PersonColumns.TABLE_NAME, values, where, whereArgs);  
  153.             break;  
  154.   
  155.         case PERSONS_ID:  
  156.             String noteId = uri.getPathSegments().get(1);  
  157.             count = db.update(Provider.PersonColumns.TABLE_NAME, values, Provider.PersonColumns._ID + "=" + noteId  
  158.                     + (!TextUtils.isEmpty(where) ? " AND (" + where + ')' : ""), whereArgs);  
  159.             break;  
  160.   
  161.         default:  
  162.             throw new IllegalArgumentException("Unknown URI " + uri);  
  163.         }  
  164.   
  165.         getContext().getContentResolver().notifyChange(uri, null);  
  166.         return count;  
  167.     }  
  168.   
  169.     static {  
  170.         sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);  
  171.         // 这个地方的persons要和PersonColumns.CONTENT_URI中最后面的一个Segment一致  
  172.         sUriMatcher.addURI(Provider.AUTHORITY, "persons", PERSONS);  
  173.         sUriMatcher.addURI(Provider.AUTHORITY, "persons/#", PERSONS_ID);  
  174.   
  175.         sPersonsProjectionMap = new HashMap<String, String>();  
  176.         sPersonsProjectionMap.put(Provider.PersonColumns._ID, Provider.PersonColumns._ID);  
  177.         sPersonsProjectionMap.put(Provider.PersonColumns.NAME, Provider.PersonColumns.NAME);  
  178.         sPersonsProjectionMap.put(Provider.PersonColumns.AGE, Provider.PersonColumns.AGE);  
  179.     }  
  180. }  


表对应的数据对象:
Person.java
  1. package com.jacp.pojos;  
  2.   
  3. public class Person {  
  4.   
  5.     public String name;  
  6.     public int age;  
  7. }  


Activity测试:
ContentProviderDemoActivity.java
  1. package com.jacp.demo;  
  2.   
  3. import android.app.Activity;  
  4. import android.content.ContentValues;  
  5. import android.database.Cursor;  
  6. import android.net.Uri;  
  7. import android.os.Bundle;  
  8. import android.text.TextUtils;  
  9. import android.util.Log;  
  10.   
  11. import com.jacp.demo.provider.Provider;  
  12. import com.jacp.pojos.Person;  
  13.   
  14. public class ContentProviderDemoActivity extends Activity {  
  15.       
  16.     private static final String TAG = "ProviderActivity";  
  17.       
  18.     @Override  
  19.     public void onCreate(Bundle savedInstanceState) {  
  20.         super.onCreate(savedInstanceState);  
  21.         setContentView(R.layout.main);  
  22.           
  23.         test();  
  24.     }  
  25.       
  26.     private void test() {  
  27.         Person p = new Person();  
  28.         p.name = "jacp";  
  29.         p.age = 99;  
  30.         int id = insert(p);  
  31.         query(id);  
  32.     }  
  33.       
  34.     private int insert(Person person) {  
  35.         ContentValues values = new ContentValues();  
  36.         values.put(Provider.PersonColumns.NAME, person.name);  
  37.         values.put(Provider.PersonColumns.AGE, person.age);  
  38.         Uri uri = getContentResolver().insert(Provider.PersonColumns.CONTENT_URI, values);  
  39.         Log.i(TAG, "insert uri="+uri);  
  40.         String lastPath = uri.getLastPathSegment();  
  41.         if (TextUtils.isEmpty(lastPath)) {  
  42.             Log.i(TAG, "insert failure!");  
  43.         } else {  
  44.             Log.i(TAG, "insert success! the id is " + lastPath);  
  45.         }  
  46.           
  47.         return Integer.parseInt(lastPath);  
  48.     }  
  49.       
  50.     private void query(int id) {  
  51.         Cursor c = getContentResolver().query(Provider.PersonColumns.CONTENT_URI, new String[] { Provider.PersonColumns.NAME, Provider.PersonColumns.AGE }, Provider.PersonColumns._ID + "=?"new String[] { id + "" }, null);  
  52.         if (c != null && c.moveToFirst()) {  
  53.             Person p = new Person();  
  54.             p.name = c.getString(c.getColumnIndexOrThrow(Provider.PersonColumns.NAME));  
  55.             p.age = c.getInt(c.getColumnIndexOrThrow(Provider.PersonColumns.AGE));  
  56.             Log.i(TAG, "person.name="+p.name+"---person.age="+p.age);  
  57.         } else {  
  58.             Log.i(TAG, "query failure!");  
  59.         }  
  60.     }  
  61. }  

Manifest.xml文件中注册配置:

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     package="com.jacp.demo"  
  4.     android:versionCode="1"  
  5.     android:versionName="1.0" >  
  6.   
  7.     <uses-sdk android:minSdkVersion="8" />  
  8.   
  9.     <application  
  10.         android:icon="@drawable/ic_launcher"  
  11.         android:label="@string/app_name" >  
  12.         <activity  
  13.             android:label="@string/app_name"  
  14.             android:name=".ContentProviderDemoActivity" >  
  15.             <intent-filter >  
  16.                 <action android:name="android.intent.action.MAIN" />  
  17.   
  18.                 <category android:name="android.intent.category.LAUNCHER" />  
  19.             </intent-filter>  
  20.         </activity>  
  21.           
  22.         <!-- 注意这个地方的位置,是在application标签里面;android:authorities对应Provider.AUTHORITY -->  
  23.         <provider android:name=".provider.PersonProvider"  
  24.             android:authorities="com.jacp.provider.demo.person" />  
  25.           
  26.     </application>  
  27.   
  28. </manifest>  

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

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

转:http://blog.csdn.net/maylian7700/article/details/7365368

如有遗漏不当之处,欢迎批评指正!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值