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

内容提供者(ContentProvider)
    1.什么是ContentProvider

                 ContentProvider可以用来把程序中的数据对外进行共享, 提供增删改查的方法(从而避免其他应用直接操作数据库产生不必要的麻烦)

                 比如只给A应用提供查询的方法,增删改都不提供。

                 ContentProvider中可以注册观察者, 监听数据的变化

      2.怎么创建内容提供者
                  定义类继承ContentProvider, 实现增删改查抽象方法

                  在清单文件中注册

<!-- 
内容提供者的路径 相对于manifest标签中的package来说的
内容提供者的别名  别的应用用 content://com.xxc.test.provider  来访问此内容提供者
-->
<provider 
    android:name=".provider.SQLiteProvider"   
    android:authorities="com.xxc.test.provider"
/>

      3.在手机上注册内容提供者
                   将应用安装到手机上即可, 可以不用运行程序
      4.怎么访问内容提供者
                   获取解析器ContentResolver, 指定Uri
                   通过ContentResolver.insert(), delete(), update(), query()方法访问Uri关联的ContentProvider
      5.Uri的处理
                   使用UriMatcher可以检查传入的Uri是否和指定的匹配

                  如果Uri带了id, 可以使用ContentUris获取id, 插入方法可以使用ContentUris给Uri加上id



ContentUris.withAppendedId(contentUri, id)//向指定Uri后追加id
ContentUris.parseId(contentUri)//解析ID


内容提供者类

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;

import com.xxc.dao.MySQLiteOpenHelper;

/**
 * 在别的应用调用内容提供者的方法
 * 1.内容提供者这个类要继承ContentProvider,实现增删改差和getType方法
 * 2.在别的应用中
 * 		ContentResolver resolver = getContext().getContentResolver();
 *      resolver.当前类里的方法      在别的应用调用此类方法的时候必定要带uri,指明调用哪个内容提供者
 */
public class SQLiteProvider extends ContentProvider {
	//Uri匹配器,用来匹配传入的Uri
	private UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);//随便传一个参数表示没有匹配上  传入-1也行

	private static final int PERSON = 1;
	private static final int STUDENT = 2;
	private static final int PERSON_ID = 3;

	private MySQLiteOpenHelper helper;

	@Override
	public boolean onCreate() {//第一次启动时执行,然后会长期驻留在后台,除非杀死进程,否则不会再执行
		/* 第一个参数:是内容提供者的别名
		 * 第二个参数:表名(就是/后的内容是什么)
		 * 第三个参数:匹配上以后,返回的值
		 */
		matcher.addURI("com.xxc.test.provider", "person", PERSON);
		matcher.addURI("com.xxc.test.provider", "person/#", PERSON_ID);
		matcher.addURI("com.xxc.test.provider", "student", STUDENT);
		helper = new MySQLiteOpenHelper(getContext());
		return true;//表示加载成功
	}

	@Override
	public Cursor query(Uri uri, String[] projection, String selection,	String[] selectionArgs, String sortOrder) {
		SQLiteDatabase db = helper.getReadableDatabase();
		Cursor c = null;
		switch (matcher.match(uri)) {//判断uri匹配后返回的值
		case PERSON_ID:
			//获取Uri最后的id内容
			long id = ContentUris.parseId(uri);
			//如果查询条件为null,那么就加上id的查询条件,如果不为null,就在查询条件的基础上加上id查询条件
			selection = selection==null?"id="+id: selection + " AND id="+id;
			//这里不写break,因为这里的判断必须经过
		case PERSON:
			c = db.query("person", projection, selection, selectionArgs, null, null, sortOrder);
			return c;
		case STUDENT:
			System.out.println("查询学生表");
			return c;
		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","name,balance", 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)) {//判断uri匹配后返回的值
		case PERSON_ID:
			long id = ContentUris.parseId(uri);
			selection = selection==null?"id="+id: selection + " AND id="+id;
		case PERSON:
			int count = db.delete("person", selection, selectionArgs);
			return count;
		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)) {//判断uri匹配后返回的值
		case PERSON_ID:
			long id = ContentUris.parseId(uri);
			selection = selection==null?"id="+id: selection + " AND id="+id;
		case PERSON:
			int count = db.update("person", values, selection, selectionArgs);
			return count;
		default:
			throw new RuntimeException("URI不能被识别---->"+uri);
		}
	}
	
	@Override
	public String getType(Uri uri) {
		switch (matcher.match(uri)) {//判断uri匹配后返回的值
		case PERSON_ID:
			return "vnd.android.cursor.item/person";//返回mimetype  这个表示一条数据
		case PERSON:
			return "vnd.android.cursor.dir/person";//返回一堆数据
		default:
			throw new RuntimeException("URI不能被识别---->"+uri);
		}
	}

}


内容提供者所在应用的AndroidManifest.xml文件

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.xxc.test"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="10" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name=".SimpleCursorAdapterActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <!-- 配置内容提供者 -->
        <provider 
            android:name=".provider.SQLiteProvider"
            android:authorities="com.xxc.test.provider"
            />
    </application>

</manifest>


使用内容提供者的类

import android.content.ContentResolver;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.test.AndroidTestCase;

import com.xxc.domain.Person;

public class ProviderTest extends AndroidTestCase {
	/**
	 * 虽然每个测试方法都用到
	 * ContentResolver resolver = getContext().getContentResolver();
	 * 但是这句话的创建动作不能写在成员变量上,因为getContext()为null
	 * 写在成员变量上的执行顺序:
	 * .class->.dex->.apk->安装->开启进程(开启主线程)->创建ProviderTest对象->getContext()->setContext()自动执行的->测试方法
	 * 写在测试方法中的执行顺序:
	 * .class->.dex->.apk->安装->开启进程(开启主线程)->创建ProviderTest对象->setContext()自动执行的->测试方法->getContext()
	 */
	public void test1(){
		ContentResolver resolver = getContext().getContentResolver();
		
	}
	
	public void testQuery(){
		ContentResolver resolver = getContext().getContentResolver();
		Uri uri = Uri.parse("content://com.xxc.test.provider/person");
		Cursor c = resolver.query(uri, null, "balance>?", new String[]{"100"}, "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.xxc.test.provider/person");
		ContentValues values = new ContentValues();
		values.put("name", "xiaoxiongmao");
		values.put("balance", 2000);
		uri = resolver.insert(uri, values);
		System.out.println(uri);
	}
	
	public void testDelete(){
		ContentResolver resolver = getContext().getContentResolver();
		Uri uri = Uri.parse("content://com.xxc.test.provider/person");
		//由于Provider解析了url后带的id,所以这边就没指定条件了,如果url后没带id就删除所有的(update同理)
		int count = resolver.delete(uri, null, null);
		System.out.println("删除了---->"+count+"条");
	}
	
	public void testUpdate(){
		ContentResolver resolver = getContext().getContentResolver();
		Uri uri = Uri.parse("content://com.xxc.test.provider/person/2");
		ContentValues values = new ContentValues();
		values.put("name", "xiaolaohu");
		values.put("balance", 10);
		int count = resolver.update(uri, values, null,null);
		System.out.println("更新了---->"+count+"条");
	}
	
	public void testGetType(){
		ContentResolver resolver = getContext().getContentResolver();
		String type1 = resolver.getType(Uri.parse("content://com.xxc.test.provider/person"));
		String type2 = resolver.getType(Uri.parse("content://com.xxc.test.provider/person/1"));
		System.out.println(type1);
		System.out.println(type2);
	}
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值