Android四大组件之ContentProvider:诞生缘由,ContentProvider内容提供者,ContentResolver内容解析器
作者:互联网
简介
诞生缘由
功能需求: 一个应用需要访问另一个应用的数据库表数据
实际情况: 一个应用的数据库文件是应用私有的, 其它应用不能直接访问
比如最直观的的手机联系人和短信两个应用:
很多时候我们发短信,接收者不是我们自己输入的,而是从联系人里面进行读取的
但是这样就出现问题了,联系人里面的数据是私有的,其他的应用是无法读取的
但是这样的功能又是经常性的需求,所以Android就在联系人这个应用里面
增加一个ContentProvider组件,这个组件暴露接口提供其他的应用访问
然后其他的应用就使用ContentResolver来调用ContentProvider提供的接口方法
来访问其他应用的数据
ContentProvider是四大应用组件之一
当前应用使用ContentProvider将数据库表数据操作暴露给其它应用访问
其它应用需要使用ContentResolver来调用ContentProvider的方法
它们之间的调用是通过Uri来进行交流的
API
ContentProvider : 内容提供者类
//provider对象创建后调用(应用安装成功或手机启动完成)
public abstract boolean onCreate();
//查询表数据
Cursor query(Uri uri, String[] projection,String selection, String[] selectionArgs)
//插入表数据
Uri insert(Uri uri, ContentValues values);
//删除表数据
int delete(Uri uri, String selection, String[] selectionArgs)
//更新表数据
update(Uri uri, ContentValues values, String selection,String[] selectionArgs);
ContentResolver: 内容提供者的解析类
//得到它的对象
context.getContentResolver()
//调用provider进行数据库CRUD操作
Insert()、delete()、update()、query()
//注册uri的监听
registerContentObserver(Uri uri, boolean notify,ContentObserver observer)
//解注册uri的监听
unregisterContentObserver(ContentObserver observer)
//通知监听器
notifyChange(Uri uri, ContentObserver observer)
Uri: 包含请求地址数据的类
//得到这个对象
Uri static parse(String uriString)
注意这个uriString的格式:
<standard_prefix>://<authority>/<data_path>/<id>
<standard_prefix>://
<authority>
<data_path>
<id>
分别对应四部分
<standard_prefix>://
是一个前缀,表示是由ContentProvider提供,固定不变 content://
<authority>
authority, 标识是哪个Provider,不同的Provider此部分必须不同。就是Provider全类名
<data_path>
对应于哪张表
<id>
id值, 对应表中的哪条记录
这些是工具类:
UriMatcher : 用于匹配Uri的容器
//添加一个合法的URI
void addURI(String authority, String path, int code)
//匹配指定的uri, 返回匹配码
int match(Uri uri)
上面两个方法,比如实际情况,A想向B访问数据,传过来一个uri
但是B接收到A传过来的uri不一定是合法的,所以B先自己添加
一些合法的uri,后面的code就是合法uri的标识,然后利用match进行匹配
如果是合法的uri就会匹配成功,返回合法uri的标识code
ContentUris : 解析uri的工具类
//解析uri, 得到其中的id
long parseId(Uri contentUri)
//添加id到指定的uri中
Uri withAppendedId(Uri contentUri, long id)
例子
ContentProvider
前期准备好数据
package com.jane.provider;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
public class DBHelper extends SQLiteOpenHelper
{
public DBHelper(Context context)
{
super(context, "atguigu.db", null, 1);
}
@Override
public void onCreate(SQLiteDatabase db)
{
Log.e("TAG", "onCreate()...");
// 建表
db.execSQL("create table person(_id integer primary key autoincrement, name varchar)");
// 插入初始化数据
db.execSQL("insert into person (name) values ('Tom')");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
{
}
}
编写ContentProvider子类
package com.jane.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;
import android.util.Log;
/**
* 操作person表的provider类
*/
public class PersonProvider extends ContentProvider
{
// 用来存放所有合法的Uri的容器
private static UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
// 保存一些合法的uri
// content://com.jane.provider.personprovider/person 不根据id操作
// content://com.jane.provider.personprovider/person/3 根据id操作
static
{
matcher.addURI("com.jane.provider.personprovider", "/person", 1);
matcher.addURI("com.jane.provider.personprovider", "/person/#",2); // #匹配任意数字
}
private DBHelper dbHelper;
public PersonProvider()
{
Log.e("TAG", "PersonProvider()");
}
@Override
public boolean onCreate()
{
Log.e("TAG", "PersonProvider onCreate()");
dbHelper = new DBHelper(getContext());
return false;
}
/**
* content://com.jane.provider.personprovider/person 不根据id查询
* content://com.jane.provider.personprovider/person/3 根据id查询
*/
@Override
public Cursor query(Uri uri, String[] projection, String selection,String[] selectionArgs, String sortOrder)
{
Log.e("TAG", "PersonProvider query()");
// 得到连接对象
SQLiteDatabase database = dbHelper.getReadableDatabase();
// 1.匹配uri, 返回code
int code = matcher.match(uri);
// 如果合法, 进行查询
if (code == 1)
{// 不根据id查询
Cursor cursor = database.query("person", projection, selection,selectionArgs, null, null, null);
return cursor;
} else if (code == 2)
{// 根据id查询
// 得到id
long id = ContentUris.parseId(uri);
// 查询
Cursor cursor = database.query("person", projection, "_id=?",new String[]{ id + "" }, null, null, null);
return cursor;
} else
{// 如果不合法, 抛出异常
throw new RuntimeException("查询的uri不合法");
}
}
/**
* content://com.jane.provider.personprovider/person 插入
* content://com.jane.provider.personprovider/person/3 根据id插入(没有)
*/
@Override
public Uri insert(Uri uri, ContentValues values)
{
Log.e("TAG", "PersonProvider insert()");
// 得到连接对象
SQLiteDatabase database = dbHelper.getReadableDatabase();
// 匹配uri, 返回code
int code = matcher.match(uri);
// 如果合法, 进行插入
if (code == 1)
{
long id = database.insert("person", null, values);
// 将id添加到uri中
uri = ContentUris.withAppendedId(uri, id);
database.close();
return uri;
} else
{
// 如果不合法, 抛出异常
database.close();
throw new RuntimeException("插入的uri不合法");
}
}
/**
* content://com.jane.provider.personprovider/person 不根据id删除
* content://com.jane.provider.personprovider/person/3 根据id删除
*/
@Override
public int delete(Uri uri, String selection, String[] selectionArgs)
{
Log.e("TAG", "PersonProvider delete()");
// 得到连接对象
SQLiteDatabase database = dbHelper.getReadableDatabase();
// 匹配uri, 返回code
int code = matcher.match(uri);
int deleteCount = -1;
// 如果合法, 进行删除
if (code == 1)
{
deleteCount = database.delete("person", selection, selectionArgs);
} else if (code == 2)
{
long id = ContentUris.parseId(uri);
deleteCount = database.delete("person", "_id=" + id, null);
} else
{
// 如果不合法, 抛出异常
database.close();
throw new RuntimeException("删除的uri不合法");
}
database.close();
return deleteCount;
}
/**
* content://com.jane.provider.personprovider/person 不根据id更新
* content://com.jane.provider.personprovider/person/3 根据id更新
*/
@Override
public int update(Uri uri, ContentValues values, String selection,String[] selectionArgs)
{
Log.e("TAG", "PersonProvider update()");
// 得到连接对象
SQLiteDatabase database = dbHelper.getReadableDatabase();
// 匹配uri, 返回code
int code = matcher.match(uri);
int updateCount = -1;
// 如果合法, 进行更新
if (code == 1)
{
updateCount = database.update("person", values, selection,
selectionArgs);
} else if (code == 2)
{
long id = ContentUris.parseId(uri);
updateCount = database.update("person", values, "_id=" + id, null);
} else
{
// 如果不合法, 抛出异常
database.close();
throw new RuntimeException("更新的uri不合法");
}
database.close();
return updateCount;
}
@Override
public String getType(Uri uri)
{
return null;
}
}
然后将ContentProvider注册到文件清单里面
<provider
android:name="com.jane.provider.PersonProvider"
android:authorities="com.jane.provider.personprovider"
android:exported="true" />
<!--
android:exported : 是否可以让其它应用访问
android:authorities是给这个内容提供者一个唯一的标识
-->
注意:
第一次调用getWritableDatabase()或getReadableDatabase()方法后,
SQLiteOpenHelper会缓存当前的SQLiteDatabase实例,
SQLiteDatabase实例正常情况下会维持数据库的打开状态,
所以在你不再需要SQLiteDatabase实例时,请及时调用close()方法释放资源。
一旦SQLiteDatabase实例被缓存,
多次调用getWritableDatabase()或getReadableDatabase()方法得到的都是同一实例。
ContentResolver
package com.jane.resolver;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
public class MainActivity extends Activity
{
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
/*
* 通过ContentResolver调用ContentProvider插入一条记录
*/
public void insert(View v)
{
// 1. 得到ContentResolver对象
ContentResolver resolver = getContentResolver();
// 2. 调用其insert
Uri uri = Uri.parse("content://com.jane.provider.personprovider/person");
// uri =
// Uri.parse("content://com.jane.provider.personprovider/person/3");
ContentValues values = new ContentValues();
values.put("name", "JACK");
uri = resolver.insert(uri, values);
Toast.makeText(this, uri.toString(), 1).show();
}
/*
* 通过ContentResolver调用ContentProvider更新一条记录
*/
public void update(View v)
{
// 1. 得到ContentResolver对象
ContentResolver resolver = getContentResolver();
// 2. 执行update
Uri uri = Uri.parse("content://com.jane.provider.personprovider/person/2");
ContentValues values = new ContentValues();
values.put("name", "JACK2");
int updateCount = resolver.update(uri, values, null, null);
Toast.makeText(this, "updateCount=" + updateCount, 1).show();
}
/*
* 通过ContentResolver调用ContentProvider删除一条记录
*/
public void delete(View v)
{
// 1. 得到ContentResolver对象
ContentResolver resolver = getContentResolver();
// 2. 执行delete
Uri uri = Uri.parse("content://com.jane.provider.personprovider/person/2");
int deleteCount = resolver.delete(uri, null, null);
Toast.makeText(this, "deleteCount=" + deleteCount, 1).show();
}
/*
* 通过ContentResolver调用ContentProvider查询所有记录
*/
public void query(View v)
{
// 1. 得到ContentResolver对象
ContentResolver resolver = getContentResolver();
// 2. 调用其query, 得到cursor
Uri uri = Uri.parse("content://com.jane.provider.personprovider/person/1");
uri = Uri.parse("content://com.jane.provider.personprovider/person");
Cursor cusor = resolver.query(uri, null, null, null, null);
// 3. 取出cursor中的数据, 并显示
while (cusor.moveToNext())
{
int id = cusor.getInt(0);
String name = cusor.getString(1);
Toast.makeText(this, id + " : " + name, 1).show();
}
cusor.close();
}
}
标签:解析器,uri,ContentResolver,Uri,content,person,provider,ContentProvider,id 来源: https://blog.csdn.net/qq_43416157/article/details/111240668