码迷,mamicode.com
首页 > 移动开发 > 详细

Android四大组件之内容提供者--ContentProvider

时间:2015-06-28 12:41:20      阅读:118      评论:0      收藏:0      [点我收藏+]

标签:android   四大组件   contentprovider   urimatcher   contentresolver   

Android四大组件之内容提供者--ContentProvider 

	1,什么是ContentProvider
		ContentProvider将应用中的数据对其它应用进行共享, 提供增删改查的方法
		ContentProvider统一了数据的访问方式,不必针对不同数据类型采取不同的访问策略
		ContentProvider将数据封装,只暴露出我们希望提供给其它程序的数据
		ContentProvider中可以注册观察者, 监听数据的变化
		
	2,怎么创建
		2.1定义类继承ContentProvider, 实现抽象方法
		2.2在清单文件中注册:在清单文件的<application>节点下进行配置<provider>标签,标签中需要指定name和authorities属性
			name:完整的类名。可以省略包名(manifest节点的package值),注意:省略后的类名是以"."开头的。
			authorities:是访问Provider时的路径,要唯一
			
	3,在手机上注册
		将应用安装到手机上即可, 不用运行程序
		
	4,其它应用怎么访问
		外部应用使用ContentResolver类对ContentProvider中的数据进行访问(CRUD操作)
			获取解析器ContentResolver
				ContentResolver resolver = Context.getContentResolver();
			通过resolver.insert(), delete(), update(), query()方法访问Uri关联的ContentProvider
			
	5,Uri的处理
	
		URI代表要操作的数据,由scheme、authorites、path三部分组成
			eg:
				content://com.jxn.provider/person
				scheme   |   authorites   | path

		1,schema:表明要访问ContentProvider。固定为:"content://"
		2,Authority(主机名或授权):定义了是哪个ContentProvider提供这些数据。
		3,path:路径,可根据业务逻辑自定义。eg: person、person/insert、person/insert/10等等
		4,ID:通常定义URI时使用"#"号占位符代替, 使用时替换成对应的数字
			"content://com.jxn.provider/person/#" #表示数据id(#代表任意数字)
			"content://com.jxn.provider/person/*" *来匹配任意文本


		Android系统提供了两个用于操作Uri的工具类:UriMatcher 和 ContentUris 

			1,UriMatcher类用于匹配Uri,用法如下:
			
			第一步:把你需要匹配的Uri路径全部给注册上,如下:
			
				//常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码
				UriMatcher  matcher = new UriMatcher(UriMatcher.NO_MATCH);
				//如果match()方法匹配content://com.jxn.provider.personprovider/person路径,返回匹配码为1
				matcher.addURI("com.jxn.provider.personprovider", "person", 1);//添加需要匹配uri,如果匹配就会返回匹配码
				//如果match()方法匹配content://com.jxn.provider.personprovider/person/230路径,返回匹配码为2
				matcher.addURI("com.jxn.provider.personprovider", "person/#", 2);//#号为通配符
			
			第二步:使用matcher.match(uri)方法对输入的Uri进行匹配,如果匹配成功就返回匹配码
				switch (matcher.match(Uri.parse("content://com.jxn.provider.personprovider/person/10"))) { 
					case 1
						// 相应的业务操作
						break;
					case 2
						// 相应的业务操作
						break;
					default:
						// 相应的业务操作
						break;
				}
		
		2,ContentUris类用于为路径加上ID和获取路径的ID

				给Uri加上id:	ContentUris.withAppendedId(uri, id) 
				获取id:		ContentUris.parseId(uri)


	6,监听内容提供者数据变化
	
		1,如果ContentProvider的访问者需要知道ContentProvider中的数据发生了变化,可以在ContentProvider 发生数据变化时调用getContentResolver().notifyChange(uri, null)来通知注册在此URI上的访问者,例如:
			public class PersonContentProvider extends ContentProvider {
				public Uri insert(Uri uri, ContentValues values) {
					db.insert("person", "personid", values);
					// 注:如果没有调用notifyChange()方法,即使其它应用注册了ContentObserver,也不会知道ContentProvider中的数据的变化
					getContext().getContentResolver().notifyChange(uri, null);
				}
			}
			
		2,如果ContentProvider的访问者需要得到数据变化通知,必须使用ContentObserver对数据(用uri描述)进行监听,当监听到数据变化通知时,系统就会调用ContentObserver的onChange()方法:
			getContentResolver().registerContentObserver(Uri.parse("content://com.jxn.providers.personprovider/person"),true, new PersonObserver(new Handler()));
			public class PersonObserver extends ContentObserver{
				public PersonObserver(Handler handler) {
					super(handler);
				}
				public void onChange(boolean selfChange) {
					//此处可以进行相应的业务处理
				}
			}
			
	7,补充
		getType()方法:主要用于匹配数据类型,返回当前Uri所代表数据的MIME类型。
			如果返回数据是单条数据:vnd.android.cursor.item 
			如果返回数据是多条数据:vnd.android.cursor.dir


案例:B应用通过A应用提供的ContentProvider访问A应用中的数据

	// 提供ContentProvider的A应用中定义的SQLiteProvider
	public class SQLiteProvider extends ContentProvider {

		// Uri匹配器, 用来匹配传入的Uri
		private static final UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
		
		private static final int PERSON = 1;
		
		// DBOpenHelper extends SQLiteOpenHelper
		private DBOpenHelper helper;

		static {
			// 设置一个Uri, 如果匹配到person, 返回1
			matcher.addURI("com.jxn.sqlite.provider", "person", PERSON);
		}
		

		// 其它应用第一次访问时(此时会创建ContentProvider)执行
		// 第一次启动时执行, 然后会长期驻留在后台, 除非被杀死, 否则不会再执行
		@Override
		public boolean onCreate() {
			helper = new DBOpenHelper(getContext());
			return true;
		}

		// 外部应用使用此方法查询数据
		@Override
		public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
			SQLiteDatabase db = helper.getReadableDatabase();
			
			// 用匹配器匹配传入的uri
			switch (matcher.match(uri)) {
				case PERSON:
					return db.query("person", projection, selection, selectionArgs, null, null, sortOrder);		// 执行查询
				default:
					throw new RuntimeException("Uri不能识别: " + uri);
			}
		}

		// 外部应用使用此方法添加数据
		@Override
		public Uri insert(Uri uri, ContentValues values) {
			SQLiteDatabase db = helper.getWritableDatabase();
			switch (matcher.match(uri)) {
				case PERSON:
					long id = db.insert("person", "id", values);	// 插入记录, 得到id
					return ContentUris.withAppendedId(uri, id);		// 把id跟在uri后面返回
				default:
					throw new RuntimeException("Uri不能识别: " + uri);
			}
		}

		@Override
		public int delete(Uri uri, String selection, String[] selectionArgs) {
			SQLiteDatabase db = helper.getWritableDatabase();
			switch (matcher.match(uri)) {
				case PERSON:
					return db.delete("person", selection, selectionArgs);
				default:
					throw new RuntimeException("Uri不能识别: " + uri);
			}
		}

		@Override
		public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
			SQLiteDatabase db = helper.getWritableDatabase();
			switch (matcher.match(uri)) {
				case PERSON:
					return db.update("person", values, selection, selectionArgs);
				default:
					throw new RuntimeException("Uri不能识别: " + uri);
			}
		}

		@Override
		public String getType(Uri uri) {
			switch (matcher.match(uri)) {
				case PERSON:
					return "vnd.android.cursor.dir/person";		// mimetype
				default:
					throw new RuntimeException("Uri不能识别: " + uri);
			}
		}
	}


	// B应用中要访问A应用的数据的测试类
	public class ProviderTest extends AndroidTestCase {
		
		public void test() {
		
			// 获取解析器对象
			ContentResolver resolver = getContext().getContentResolver();
			
			// 访问内容提供者
			Uri uri = Uri.parse("content://com.jxn.sqlite.provider");
			ContentValues values = new ContentValues();

		}
		
		public void testQuery() {
		
			// 获取解析器对象
			ContentResolver resolver = getContext().getContentResolver();
			Uri uri = Uri.parse("content://com.jxn.sqlite.provider/person");
			
			// 访问内容提供者
			Cursor c = resolver.query(uri, new String[]{ "id", "name", "balance" }, "balance>?", new String[]{ "9000" }, "balance DESC");
			while (c.moveToNext()) {
				Person p = new Person(c.getInt(0), c.getString(1), c.getInt(2));
				System.out.println(p);
			}
		}
		
		public void testInsert() {
			ContentResolver resolver = getContext().getContentResolver();
			Uri uri = Uri.parse("content://com.jxn.sqlite.provider/person");
			
			ContentValues values = new ContentValues();
			values.put("name", "provider");
			values.put("balance", 12345);
			
			// 插入数据, 并且得到这条数据的uri
			uri = resolver.insert(uri, values);
			
			System.out.println(uri);
		}
		
		public void testUpdate() {
			ContentResolver resolver = getContext().getContentResolver();
			Uri uri = Uri.parse("content://com.jxn.sqlite.provider/person");
			
			ContentValues values = new ContentValues();
			values.put("name", "update");
			values.put("balance", 54321);
			int count = resolver.update(uri, values, null, null);
			System.out.println(count);
		}
		
		public void testDelete() {
			ContentResolver resolver = getContext().getContentResolver();
			Uri uri = Uri.parse("content://com.jxn.sqlite.provider/person");
			
			int count = resolver.delete(uri, null, null);
			System.out.println(count);
		}
		
		public void testGetType() {
			ContentResolver resolver = getContext().getContentResolver();
			// 获取uri的类型
			String type = resolver.getType(Uri.parse("content://com.jxn.sqlite.provider/person"));
			System.out.println(type);
		}
	}
	
	
	

Android四大组件之内容提供者--ContentProvider

标签:android   四大组件   contentprovider   urimatcher   contentresolver   

原文地址:http://blog.csdn.net/wodewutai17quiet/article/details/46670597

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!