数据存贮

转载来源:http://blog.csdn.net/geekerparadise/article/details/7787729

接触Android有一段时间了,每一个知识点都有涉及,现在觉得重新把知识点理一遍很重要,那么就凭感觉、凭喜好无知识点先后顺序来理清一遍。这篇文章主要叙述了如何来自定义自己的ContentProvider组件,其中涉及到的一些比较重要的知识点也顺带详细分解一下,那么现在就开始吧。

一、SQLiteOpenHelper简介:

SQLiteOpenHelper是Android给我们提供的一个工具,用来和数据库交互的。我们通常使用的方法是自定义一个类来继承于SQLiteOpenHelper,通过它可以得到一个SQLiteDatabase的实例,通过使用此对象的一些方法来与数据库交互。

例如:

execSQL(Stringsql).传入一个字符串形式的sql语句来执行等。

insert(String table, String nullColumnHack, ContentValues values)。插入操作,table是表名,values是ContentValues类型用来携带数据的,第二个参数是为了防止values为空时后台创建SQL语句出错。具体的其他方法参考API文档,此处就不做解释。

二、ContentProvider简介:

假如你的应用程序想把一些数据提供给其他的应用程序来使用,那么此时就会用到ContentProvider,有了它你的应用程序就可以在进程间共享数据。使用的时候需要创建一个类来继承ContentProvider,实现里面的方法,这就相当于此应用给其他应用程序提供访问数据的接口。说直观点,Contentprovider就相当于一个中介人,它介于第一个应用程序的数据层和另一应用程序之间。使用了Contentprovider最重要的作用是统一了共享数据时访问数据的方式。

三、ContentResolver简介:

当外部应用程序想对ContentProvider中数据进行操作时可以使用ContentResolver来完成,要获取它的对象可以使用Activity中的getContentResolver方法来完成。

四、Uri简介:

介绍之前默认为大家都了解URL,那么URL就相当于Uri的一个子集。Uri由三部分组成:scheme、authority、path。下面举一个例子来具体介绍。

Uri:    content://com.jm.provider.myprovider/peoples

1    scheme部分:以content://开头,是Android系统定义的,不可更改。

2    authority部分:推荐以域名+provider+类名组成,也可自己定义。

3    path部分:用来表示我们要操作的数据。具体说明如下:

      要操作peoples中所有数据可以构建 /peoples

      要操作peoples中_id为1的数据可以构建/peoples/1

Uri有两个比较常用方法

1       parse(String uriString)它的作用是将字符型数据转换成Uri类型数据。

2       withAppendedPath(Uri baseUri,String pathSegment)它的作用是将baseUri后面加上pathSegment组成新的Uri。

五、UriMatcher简介:

作用是在ContentProvider中把需要匹配的Uri全部注册上。

UriMatcher.NO_MATCHER表示不匹配任何路径,返回码为-1.

UriMatcher有两个常用方法。

1       match(Uri uri)获取路径的返回码。

2       addURI(String authority, Stringpath, int code)是用来注册需要匹配的路径。具体实例参看下文。

API中推荐把它放在静态块中完成,例如:

  1. private static final UriMatcher mather = new UriMatcher(UriMatcher.NO_MATCH);  
  2.     static {  
  3.         mather.addURI(CONTENT_URI.getAuthority(), "peoples", PEOPLE);  
  4.         mather.addURI(CONTENT_URI.getAuthority(), "peoples/#", PEOPLE_ID);  
  5. }  
private static final UriMatcher mather = new UriMatcher(UriMatcher.NO_MATCH);
	static {
		mather.addURI(CONTENT_URI.getAuthority(), "peoples", PEOPLE);
		mather.addURI(CONTENT_URI.getAuthority(), "peoples/#", PEOPLE_ID);
}

其中要解释的一点是#代表通配符,表示所有数字(will match any number)。*代表所有字符(will match any text)。

六、ContentUris简介:

ContentUris是用来获取uri后面id部分,它有两个比较实用的方法:

1       parseId(Uri contentUri)用来获得contentUri中id部分

2       withAppendedId(Uri contentUri,long id)用来给contentUri添加id组成新的Uri,功能和Uri的withAppendedPath(Uri baseUri,String pathSegment)方法类似。

七、ContentProvider中getType方法中MIME类型讲解:

vnd.android.cursor.dir代表值的集合

vnd.android.cursor.item代表一项值

最好不要默认返回null

结构分析,例如:"vnd.android.cursor.dir/peoplelist" 斜杠前部分可把它比作变量的类型是不能随便定义的,后部分相当于变量名,可自己定义。

当调用增删改查方法时系统会通过getType()进行验证,如果有值并且是系统可识别的类型,那么处理起来比较快。

八、代码示例:

1、继承SQLiteOpenHelper

  1. package com.jm.my.provider;  
  2.    
  3. import android.content.ContentValues;  
  4. import android.content.Context;  
  5. import android.database.sqlite.SQLiteDatabase;  
  6. import android.database.sqlite.SQLiteOpenHelper;  
  7.    
  8. /** 
  9.  * 继承于SQLiteOpenHelper,用于和数据库交互 
  10.  * @author jinmeng 
  11.  * @date 2012-7-25 
  12.  * @version 1.0 
  13.  */  
  14. public class MyHelper extends SQLiteOpenHelper {  
  15.    
  16.        //数据库名字,可在文件目录下找到   
  17.        private static final String DATABASE_NAME = "mydb";  
  18.        //数据库版本号   
  19.        private static final int MYDATABASE_VERSION = 1;  
  20.        //数据库表名   
  21.        public static final String TABLE_NAME = "peoples";  
  22.        //数据库的一些基本字段   
  23.        public static final String COL_NAME = "name";  
  24.        public static final String COL_AGE = "age";  
  25.        public static final String COL_BIRTHDAY = "birthday";  
  26.        //创建数据库时的SQL语句   
  27.        public static final String CREATEDATABASE = "CREATE TABLE " + TABLE_NAME  
  28.                      + " (_id INTEGER PRIMARY KEYAUTOINCREMENT, " + COL_NAME  
  29.                      + " TEXT, " + COL_AGE + " INTEGER, " + COL_BIRTHDAY + " DATE);";  
  30.    
  31.        public MyHelper(Context context) {  
  32.               super(context, DATABASE_NAME, null, MYDATABASE_VERSION);  
  33.        }  
  34.    
  35.        /** 
  36.         * 当数据库被创建的时候执行SQL语句 
  37.         */  
  38.        @Override  
  39.        public void onCreate(SQLiteDatabase db) {  
  40.               db.execSQL(CREATEDATABASE);  
  41.               ContentValues cv = new ContentValues();  
  42.               cv.put(COL_NAME, "jinmeng");  
  43.               cv.put(COL_AGE, 22);  
  44.               String str = new String("1990-03-09");  
  45.               cv.put(COL_BIRTHDAY, str);  
  46.               db.insert(TABLE_NAME, null, cv);  
  47.        }  
  48.    
  49.        /** 
  50.         * 当数据库版本号更新的时候回调此方法。 
  51.         */  
  52.        @Override  
  53.        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {  
  54.               db.execSQL("DROP TABLE IF EXIST" + TABLE_NAME);  
  55.               onCreate(db);  
  56.        }  
  57. }  
package com.jm.my.provider;
 
import android.content.ContentValues;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
 
/**
 * 继承于SQLiteOpenHelper,用于和数据库交互
 * @author jinmeng
 * @date 2012-7-25
 * @version 1.0
 */
public class MyHelper extends SQLiteOpenHelper {
 
       //数据库名字,可在文件目录下找到
       private static final String DATABASE_NAME = "mydb";
       //数据库版本号
       private static final int MYDATABASE_VERSION = 1;
       //数据库表名
       public static final String TABLE_NAME = "peoples";
       //数据库的一些基本字段
       public static final String COL_NAME = "name";
       public static final String COL_AGE = "age";
       public static final String COL_BIRTHDAY = "birthday";
       //创建数据库时的SQL语句
       public static final String CREATEDATABASE = "CREATE TABLE " + TABLE_NAME
                     + " (_id INTEGER PRIMARY KEYAUTOINCREMENT, " + COL_NAME
                     + " TEXT, " + COL_AGE + " INTEGER, " + COL_BIRTHDAY + " DATE);";
 
       public MyHelper(Context context) {
              super(context, DATABASE_NAME, null, MYDATABASE_VERSION);
       }
 
       /**
        * 当数据库被创建的时候执行SQL语句
        */
       @Override
       public void onCreate(SQLiteDatabase db) {
              db.execSQL(CREATEDATABASE);
              ContentValues cv = new ContentValues();
              cv.put(COL_NAME, "jinmeng");
              cv.put(COL_AGE, 22);
              String str = new String("1990-03-09");
              cv.put(COL_BIRTHDAY, str);
              db.insert(TABLE_NAME, null, cv);
       }
 
       /**
        * 当数据库版本号更新的时候回调此方法。
        */
       @Override
       public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
              db.execSQL("DROP TABLE IF EXIST" + TABLE_NAME);
              onCreate(db);
       }
}

2、为示例添加ContentProvider类:

  1. package com.jm.my.provider;  
  2.   
  3. import android.content.ContentProvider;  
  4. import android.content.ContentUris;  
  5. import android.content.ContentValues;  
  6. import android.content.UriMatcher;  
  7. import android.database.Cursor;  
  8. import android.database.sqlite.SQLiteDatabase;  
  9. import android.net.Uri;  
  10.   
  11. /** 
  12.  * 继承于ContentProvider,提供外接访问接口 
  13.  *  
  14.  * @author jinmeng 
  15.  * @date 2012-7-25 
  16.  * @version 1.0 
  17.  */  
  18. public class MyProvider extends ContentProvider {  
  19.   
  20.     // 和Authority相关   
  21.     public static final Uri CONTENT_URI = Uri  
  22.             .parse("content://com.jm.provider.myprovider/peoples");  
  23.     // 数据库表名   
  24.     private static final String TABLE_NAME = "peoples";  
  25.     // 注册和解析路径时的返回码   
  26.     private static final int PEOPLE = 1;  
  27.     private static final int PEOPLE_ID = 2;  
  28.     // 注册需要的路径   
  29.     private static final UriMatcher mather = new UriMatcher(UriMatcher.NO_MATCH);  
  30.     static {  
  31.         mather.addURI(CONTENT_URI.getAuthority(), "peoples", PEOPLE);  
  32.         mather.addURI(CONTENT_URI.getAuthority(), "peoples/#", PEOPLE_ID);  
  33.     }  
  34.   
  35.     private MyHelper helper;  
  36.   
  37.     /** 
  38.      * 基本表结构 
  39.      *  
  40.      * @author jinmeng 
  41.      *  
  42.      */  
  43.     public static final class Mydata {  
  44.         public static final String COL_ID = "_id";  
  45.         public static final String COL_NAME = "name";  
  46.         public static final String COL_AGE = "age";  
  47.         public static final String COL_BIRTHDAY = "birthday";  
  48.     }  
  49.   
  50.     @Override  
  51.     public boolean onCreate() {  
  52.         this.helper = new MyHelper(this.getContext());  
  53.         if (helper != null) {  
  54.             return true;  
  55.         } else {  
  56.             return false;  
  57.         }  
  58.     }  
  59.     /** 
  60.      * 启动时涉及到的MIME类型值: vnd.android.cursor.dir代表值的集合 vnd.android.cursor.item代表一项值 
  61.      * 最好不要默认返回空 
  62.      */  
  63.     @Override  
  64.     public String getType(Uri uri) {  
  65.         switch (mather.match(uri)) {  
  66.         case PEOPLE:  
  67.             return "vnd.android.cursor.dir/peoplelist";  
  68.         case PEOPLE_ID:  
  69.             return "vnd.android.cursor.item/peopleitem";  
  70.         default:  
  71.             throw new IllegalArgumentException("uri Illegal" + uri);  
  72.         }  
  73.     }  
  74.     /** 
  75.      * 具体的查询方法 
  76.      */  
  77.     @Override  
  78.     public Cursor query(Uri uri, String[] projection, String selection,  
  79.             String[] selectionArgs, String sortOrder) {  
  80.         SQLiteDatabase db = helper.getWritableDatabase();  
  81.         switch (mather.match(uri)) {  
  82.         case PEOPLE:  
  83.             return db.query(TABLE_NAME, projection, selection, selectionArgs,  
  84.                     nullnull, sortOrder);  
  85.         case PEOPLE_ID:  
  86.             long id = ContentUris.parseId(uri);  
  87.             String where = "_id=" + id;  
  88.             if ((selection != null) && (!"".equals(selection))) {  
  89.                 where = where + " and " + selection;  
  90.             }  
  91.             return db.query(TABLE_NAME, projection, where, selectionArgs, null,  
  92.                     null, sortOrder);  
  93.         default:  
  94.             throw new IllegalArgumentException("uri Illegal" + uri);  
  95.         }  
  96.     }  
  97.     /** 
  98.      * 具体的插入方法 
  99.      */  
  100.     @Override  
  101.     public Uri insert(Uri uri, ContentValues values) {  
  102.         SQLiteDatabase db = helper.getWritableDatabase();  
  103.         long id;  
  104.         switch (mather.match(uri)) {  
  105.         case PEOPLE:  
  106.             id = db.insert(TABLE_NAME, "_id", values);  
  107.             return ContentUris.withAppendedId(uri, id);  
  108.         case PEOPLE_ID:  
  109.             id = db.insert(TABLE_NAME, "_id", values);  
  110.             String uriPath = uri.toString();  
  111.             String path = uriPath.substring(0, uriPath.lastIndexOf("/")) + id;  
  112.             return Uri.parse(path);  
  113.         default:  
  114.             throw new IllegalArgumentException("uri Illegal" + uri);  
  115.         }  
  116.     }  
  117.     /** 
  118.      * 具体的删除方法 
  119.      */  
  120.     @Override  
  121.     public int delete(Uri uri, String selection, String[] selectionArgs) {  
  122.         SQLiteDatabase db = helper.getWritableDatabase();  
  123.         switch (mather.match(uri)) {  
  124.         case PEOPLE:  
  125.             return db.delete(TABLE_NAME, selection, selectionArgs);  
  126.         case PEOPLE_ID:  
  127.             long id = ContentUris.parseId(uri);  
  128.             String where = "_id=" + id;  
  129.             if ((selection != null) && (!"".equals(selection))) {  
  130.                 where = where + " and " + selection;  
  131.             }  
  132.             return db.delete(TABLE_NAME, where, selectionArgs);  
  133.         default:  
  134.             throw new IllegalArgumentException("uri Illegal" + uri);  
  135.         }  
  136.     }  
  137.     /** 
  138.      * 具体的更新方法 
  139.      */  
  140.     @Override  
  141.     public int update(Uri uri, ContentValues values, String selection,  
  142.             String[] selectionArgs) {  
  143.         SQLiteDatabase db = helper.getWritableDatabase();  
  144.         switch (mather.match(uri)) {  
  145.         case PEOPLE:  
  146.             return db.update(TABLE_NAME, values, selection, selectionArgs);  
  147.         case PEOPLE_ID:  
  148.             long id = ContentUris.parseId(uri);  
  149.             String where = "_id=" + id;  
  150.             if ((selection != null) && (!"".equals(selection))) {  
  151.                 where = where + " and " + selection;  
  152.             }  
  153.             return db.update(TABLE_NAME, values, where, selectionArgs);  
  154.         default:  
  155.             throw new IllegalArgumentException("uri Illegal" + uri);  
  156.         }  
  157.     }  
  158. }  
package com.jm.my.provider;

import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;

/**
 * 继承于ContentProvider,提供外接访问接口
 * 
 * @author jinmeng
 * @date 2012-7-25
 * @version 1.0
 */
public class MyProvider extends ContentProvider {

	// 和Authority相关
	public static final Uri CONTENT_URI = Uri
			.parse("content://com.jm.provider.myprovider/peoples");
	// 数据库表名
	private static final String TABLE_NAME = "peoples";
	// 注册和解析路径时的返回码
	private static final int PEOPLE = 1;
	private static final int PEOPLE_ID = 2;
	// 注册需要的路径
	private static final UriMatcher mather = new UriMatcher(UriMatcher.NO_MATCH);
	static {
		mather.addURI(CONTENT_URI.getAuthority(), "peoples", PEOPLE);
		mather.addURI(CONTENT_URI.getAuthority(), "peoples/#", PEOPLE_ID);
	}

	private MyHelper helper;

	/**
	 * 基本表结构
	 * 
	 * @author jinmeng
	 * 
	 */
	public static final class Mydata {
		public static final String COL_ID = "_id";
		public static final String COL_NAME = "name";
		public static final String COL_AGE = "age";
		public static final String COL_BIRTHDAY = "birthday";
	}

	@Override
	public boolean onCreate() {
		this.helper = new MyHelper(this.getContext());
		if (helper != null) {
			return true;
		} else {
			return false;
		}
	}
	/**
	 * 启动时涉及到的MIME类型值: vnd.android.cursor.dir代表值的集合 vnd.android.cursor.item代表一项值
	 * 最好不要默认返回空
	 */
	@Override
	public String getType(Uri uri) {
		switch (mather.match(uri)) {
		case PEOPLE:
			return "vnd.android.cursor.dir/peoplelist";
		case PEOPLE_ID:
			return "vnd.android.cursor.item/peopleitem";
		default:
			throw new IllegalArgumentException("uri Illegal" + uri);
		}
	}
	/**
	 * 具体的查询方法
	 */
	@Override
	public Cursor query(Uri uri, String[] projection, String selection,
			String[] selectionArgs, String sortOrder) {
		SQLiteDatabase db = helper.getWritableDatabase();
		switch (mather.match(uri)) {
		case PEOPLE:
			return db.query(TABLE_NAME, projection, selection, selectionArgs,
					null, null, sortOrder);
		case PEOPLE_ID:
			long id = ContentUris.parseId(uri);
			String where = "_id=" + id;
			if ((selection != null) && (!"".equals(selection))) {
				where = where + " and " + selection;
			}
			return db.query(TABLE_NAME, projection, where, selectionArgs, null,
					null, sortOrder);
		default:
			throw new IllegalArgumentException("uri Illegal" + uri);
		}
	}
	/**
	 * 具体的插入方法
	 */
	@Override
	public Uri insert(Uri uri, ContentValues values) {
		SQLiteDatabase db = helper.getWritableDatabase();
		long id;
		switch (mather.match(uri)) {
		case PEOPLE:
			id = db.insert(TABLE_NAME, "_id", values);
			return ContentUris.withAppendedId(uri, id);
		case PEOPLE_ID:
			id = db.insert(TABLE_NAME, "_id", values);
			String uriPath = uri.toString();
			String path = uriPath.substring(0, uriPath.lastIndexOf("/")) + id;
			return Uri.parse(path);
		default:
			throw new IllegalArgumentException("uri Illegal" + uri);
		}
	}
	/**
	 * 具体的删除方法
	 */
	@Override
	public int delete(Uri uri, String selection, String[] selectionArgs) {
		SQLiteDatabase db = helper.getWritableDatabase();
		switch (mather.match(uri)) {
		case PEOPLE:
			return db.delete(TABLE_NAME, selection, selectionArgs);
		case PEOPLE_ID:
			long id = ContentUris.parseId(uri);
			String where = "_id=" + id;
			if ((selection != null) && (!"".equals(selection))) {
				where = where + " and " + selection;
			}
			return db.delete(TABLE_NAME, where, selectionArgs);
		default:
			throw new IllegalArgumentException("uri Illegal" + uri);
		}
	}
	/**
	 * 具体的更新方法
	 */
	@Override
	public int update(Uri uri, ContentValues values, String selection,
			String[] selectionArgs) {
		SQLiteDatabase db = helper.getWritableDatabase();
		switch (mather.match(uri)) {
		case PEOPLE:
			return db.update(TABLE_NAME, values, selection, selectionArgs);
		case PEOPLE_ID:
			long id = ContentUris.parseId(uri);
			String where = "_id=" + id;
			if ((selection != null) && (!"".equals(selection))) {
				where = where + " and " + selection;
			}
			return db.update(TABLE_NAME, values, where, selectionArgs);
		default:
			throw new IllegalArgumentException("uri Illegal" + uri);
		}
	}
}

3、添加contentProvider配置:

此处定义的

  1. android:authorities  
android:authorities
和代码中CONTENT_URI保持一致

  1. <providerandroid:name=".MyProvider"  
  2. android:authorities="com.jm.provider.myprovider"/>  
<providerandroid:name=".MyProvider"
android:authorities="com.jm.provider.myprovider"/>

4、测试ContentProvider的示例程序:

ContentProvider是给其他应用程序提供数据的接口,那么测试工程新建,以下只给出insert的测试。

  1. package com.jm.test;  
  2.   
  3. import android.app.Activity;  
  4. import android.content.ContentResolver;  
  5. import android.database.Cursor;  
  6. import android.net.Uri;  
  7. import android.os.Bundle;  
  8. import android.util.Log;  
  9.   
  10. /** 
  11.  * 用来测试ContentProvider 
  12.  * @author jinmeng 
  13.  * @date 2012-7-25 
  14.  * @version 1.0 
  15.  */  
  16. public class MainActivity extends Activity {  
  17.       
  18.     @Override  
  19.     public void onCreate(Bundle savedInstanceState) {  
  20.         super.onCreate(savedInstanceState);  
  21.         //获取ContentResolver实例   
  22.         ContentResolver contentResolver = MainActivity.this  
  23.                 .getContentResolver();  
  24.         //访问数据的Uri地址   
  25.         Uri uri = Uri.parse("content://com.jm.provider.myprovider/peoples");  
  26.         //通过ContentResolver来获取Cursor   
  27.         Cursor cursor = contentResolver.query(uri, new String[] { "_id",  
  28.                 "name""age" }, nullnull"_id desc");  
  29.         //遍例输出结果   
  30.         while (cursor.moveToNext()) {  
  31.             Log.i("jm",  
  32.                     "_id=" + cursor.getInt(0) + ",name=" + cursor.getString(1)  
  33.                             + ",age=" + cursor.getString(2));  
  34.         }  
  35.     }  
  36. }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值