自定义ContentProvider案例
1.条件准备
- app5往外暴漏数据
- app7接收和操作远程数据
图1 app5目录结构
图2 app7目录结构
2.参考代码
完整代码:
https://download.csdn.net/download/weixin_41957626/87346497
1)app5的代码
(1)app5的entity,dao,以及布局文件和activity代码详见博客SQLite数据库-学生管理系统(2.0)_简单点了的博客-CSDN博客基于SQLite数据库实现的学生管理系统,符合MVC的设计模式https://blog.csdn.net/weixin_41957626/article/details/128432736?spm=1001.2014.3001.5502
(2)app5的provider代码如下
//内容提供者
public class StudnetProvider extends ContentProvider {
//定义URI匹配规则
UriMatcher uriMatcher=new UriMatcher(UriMatcher.NO_MATCH);
//定义Provider的Uri地址
String authority =new String("com.lxz.app5");
@Override
public boolean onCreate() {
//this.getContext()获取上下文
MyHelper myHelper=new MyHelper(this.getContext(),"studentDB",1);
/*往Uri中添加规则*/
//查询所有的学生信息
uriMatcher.addURI(authority,"studentAll",1);
//根据学生编号进行模糊查询,#表示任意数字,*表示任意字符;
uriMatcher.addURI(authority,"student/#",2);
//根据学生编号进行精确查询
uriMatcher.addURI(authority,"studentVague/*",3);
//根据学生性别进行精确查询
uriMatcher.addURI(authority,"studentSexVague",4);
//插入一条学生信息
uriMatcher.addURI(authority,"insertstudnet",1);
//更新一条学生信息
uriMatcher.addURI(authority,"updatestudent",1);
//根据编号删除学生的信息
uriMatcher.addURI(authority,"deletestudent",1);
//删除表中的全部数据
uriMatcher.addURI(authority,"deletestudent/all",2);
//返回值true代表初始化成功,返回值是false代表的是初始化失败
return true;
}
@Nullable
@Override
//查询
public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String s, @Nullable String[] strings1, @Nullable String s1) {
MyHelper helper=new MyHelper(this.getContext(),"studentDB",1);
SQLiteDatabase database=helper.getWritableDatabase();
//遍历的结果
Cursor cursor=null;
System.out.println(uri);
System.out.println(uriMatcher.match(uri));
switch (uriMatcher.match(uri)){
case 1:
cursor=database.query("student",projection,null,null,null,null,null);
break;
case 2:
long id= ContentUris.parseId(uri);
cursor=database.query("student",projection,"id= ?",new String[]{""+id},null,null,s1);
break;
case 3:
//根据ContentUris的parseId提取出来id的值
//content://com.lxz.app5/student/1,就是将1提取出来
long idx= ContentUris.parseId(uri);
cursor=database.query("student",projection,"id like ?",new String[]{"%"+idx+"%"},null,null,null);
break;
case 4:
//根据性别进行模糊查询
cursor=database.query("student",projection,s,strings1,null,null,null);
break;
default:
throw new RuntimeException("未知uri");
}
return cursor;
}
//返回的MIME数据类型
@Nullable
@Override
public String getType(@NonNull Uri uri) {
return uri.getAuthority();
}
@Nullable
@Override
//插入数据
public Uri insert(@NonNull Uri uri, @Nullable ContentValues contentValues) {
MyHelper helper=new MyHelper(this.getContext(),"studentDB",1);
SQLiteDatabase database=helper.getWritableDatabase();
//遍历的结果
long id=0;
switch (uriMatcher.match(uri)){
case 1:
id =database.insert("student",null,contentValues);
break;
default:
throw new RuntimeException("未知uri");
}
database.close();
helper.close();
//为了判断是不是插入成功了,id的值为插入后的主键的号
uri=ContentUris.withAppendedId(uri,id);
return uri;
}
@Override
//删除数据
public int delete(@NonNull Uri uri, @Nullable String s, @Nullable String[] strings) {
MyHelper helper=new MyHelper(this.getContext(),"studentDB",1);
SQLiteDatabase database=helper.getWritableDatabase();
int id=0;
switch (uriMatcher.match(uri)){
case 1:
id =database.delete("student",s,strings);
break;
case 2:
id =database.delete("student",null,null);//删除表中的全部数据
default:
throw new RuntimeException("未知uri");
}
database.close();
helper.close();
return id;
}
@Override
//更新数据
public int update(@NonNull Uri uri, @Nullable ContentValues contentValues, @Nullable String s, @Nullable String[] strings) {
MyHelper helper=new MyHelper(this.getContext(),"studentDB",1);
SQLiteDatabase database=helper.getWritableDatabase();
int id=0;
switch (uriMatcher.match(uri)){
case 1:
id =database.update("student",contentValues,s,strings);
break;
default:
throw new RuntimeException("未知uri");
}
database.close();
helper.close();
return id;
}
}
(3)app5的AndroidManifest.xml文件代码
<!--注册provider-->
<provider
android:authorities="com.lxz.app5"
android:name=".provider.StudnetProvider"
android:exported="true"
android:enabled="true"
/>
2)app7的代码
(1)app7下的实体类代码。
//学生实体
public class Student implements Serializable {
//属性
private Integer id;
private String name;
private Integer age;
private Integer sex;
//构造
public Student(Integer id, String name, Integer age, Integer sex) {
this.id = id;
this.name = name;
this.age = age;
this.sex = sex;
}
//get & set
public Student() {
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Integer getSex() {
return sex;
}
public void setSex(Integer sex) {
this.sex = sex;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", sex=" + sex +
'}';
}
}
(2)app7下的布局文件代码。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="远程查询"
android:textSize="30dp"
android:textColor="@color/black"
android:gravity="center"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="studentAll"
android:textColor="@color/black"
android:textSize="30dp"
android:onClick="getStudentAll"
/>
<!--根据id精确查询-->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<EditText
android:id="@+id/textId"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:hint="ID精确查询"
android:textSize="20dp"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="getStudentById"
android:textColor="@color/black"
android:textSize="25dp"
android:onClick="getStudentById"
/>
</LinearLayout>
<!--根据id模糊查询-->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<EditText
android:id="@+id/textIdVague"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:hint="ID模糊"
android:textSize="20dp"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="getStudentByIdVague"
android:textColor="@color/black"
android:textSize="25dp"
android:onClick="getStudentByIdVague"
/>
</LinearLayout>
<!--根据sex模糊查询-->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<EditText
android:id="@+id/textAgeVague"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:hint="Age模糊"
android:textSize="20dp"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="getStudentByAgeVague"
android:textColor="@color/black"
android:textSize="24dp"
android:onClick="getStudentBySexVague"
/>
</LinearLayout>
<!--根据sex模糊查询-->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<EditText
android:id="@+id/deletetextId"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:hint="ID删除"
android:textSize="20dp"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="deleteStudentById"
android:textColor="@color/black"
android:textSize="24dp"
android:onClick="deleteStudentById"
/>
</LinearLayout>
<!--远程更新-->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="为了测试仅更新id=1的name属性"
android:gravity="center"
android:textSize="25dp"
/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<EditText
android:id="@+id/updatetextName"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:hint="name更新"
android:textSize="20dp"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="updateStudentByName"
android:textColor="@color/black"
android:textSize="24dp"
android:onClick="updateStudentByName"
/>
</LinearLayout>
<!--远程插入-->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="为了测试仅设置name属性,其余默认"
android:gravity="center"
android:textSize="25dp"
/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<EditText
android:id="@+id/inserttextName"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:hint="插入信息"
android:textSize="20dp"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="insertStudent"
android:textColor="@color/black"
android:textSize="24dp"
android:onClick="insertStudent"
/>
</LinearLayout>
</LinearLayout>
(3)app7下的Activity。
//app7用于远程调用app5中的数据
public class MainActivity extends AppCompatActivity {
ContentResolver reserve=null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getObserver();
}
//方法:获取ContentResolver对象
public void getObserver(){
reserve=getContentResolver();
}
//方法:远程查询所有的数据信息
public List<Student> remoteQueryAll(){
Uri uri=Uri.parse("content://com.lxz.app5/studentAll");
Cursor cursor=null;
List<Student> list=new ArrayList<>();
list.clear();
cursor=reserve.query(uri,new String[]{"id","name","age","sex"},null,null,null);
while (cursor.moveToNext()){
int id=cursor.getInt(0);
String name=cursor.getString(1);
int age=cursor.getInt(2);
int sex=cursor.getInt(3);
list.add(new Student(id,name,age,sex));
}
cursor.close();
System.out.println(uri.toString()+"---"+list.toString());
return list;
}
//方法:远程查询指定id的数据信息
public Student remoteQueryById(){
EditText editText=findViewById(R.id.textId);
Uri uri=Uri.parse("content://com.lxz.app5/student");
uri=ContentUris.withAppendedId(uri,Integer.parseInt(editText.getText().toString()));//拼接出带id的uri地址
Student student=null;
Cursor cursor=reserve.query(uri,new String[]{"id","name","age","sex"},null,null,null);
if (cursor.moveToNext()){
int id=cursor.getInt(0);
String name=cursor.getString(1);
int age=cursor.getInt(2);
int sex=cursor.getInt(3);
student=new Student(id,name,age,sex);
}
cursor.close();
System.out.println(uri.toString()+"---"+student.toString());
return student;
}
//方法:远程模糊查询ID的数据信息
public List<Student> remoteQueryByIdVague(){
EditText editText=findViewById(R.id.textIdVague);
Uri uri=Uri.parse("content://com.lxz.app5/studentVague");
uri=ContentUris.withAppendedId(uri,Integer.parseInt(editText.getText().toString().trim()));//拼接出带id的uri地址
List<Student> list=new ArrayList<>();
Cursor cursor=reserve.query(uri,new String[]{"id","name","age","sex"},null,null,null);
while (cursor.moveToNext()){
int id=cursor.getInt(0);
String name=cursor.getString(1);
int age=cursor.getInt(2);
int sex=cursor.getInt(3);
list.add(new Student(id,name,age,sex));
}
cursor.close();
System.out.println(uri.toString()+"---"+list.toString());
return list;
}
//方法:远程模糊查询Age的数据信息
public List<Student> remoteQueryBySexVague(){
EditText editText=findViewById(R.id.textAgeVague);
Uri uri=Uri.parse("content://com.lxz.app5/studentSexVague");
List<Student> list=new ArrayList<>();
Cursor cursor=reserve.query(uri,new String[]{"id","name","age","sex"},"age like ?",new String[]{"%"+editText.getText()+"%"},null);
while (cursor.moveToNext()){
int id=cursor.getInt(0);
String name=cursor.getString(1);
int age=cursor.getInt(2);
int sex=cursor.getInt(3);
list.add(new Student(id,name,age,sex));
}
cursor.close();
System.out.println(uri.toString()+"---"+list.toString());
return list;
}
//远程删除指定id对应的学生的信息
public void remoteDeleteStudnet(){
EditText editText=findViewById(R.id.deletetextId);
Uri uri=Uri.parse("content://com.lxz.app5/deletestudent");
long x=reserve.delete(uri,"id=?",new String[]{editText.getText().toString()});
System.out.println(uri.toString()+"----"+(x>=1 ? "删除成功":"删除失败"));
}
//远程更新指定id对应的学生的信息
public void remoteUpdateStudnet(){
EditText editText=findViewById(R.id.updatetextName);
Uri uri=Uri.parse("content://com.lxz.app5/updatestudent");
ContentValues values=new ContentValues();
values.put("name",editText.getText().toString());
long x=reserve.update(uri,values,"id=?",new String[]{"1"});
System.out.println(uri.toString()+"----"+(x>=1 ? "更新成功":"更新失败"));
}
//远程插入学生信息
public void remoteInsertStudnet(){
EditText editText=findViewById(R.id.inserttextName);
Uri uri=Uri.parse("content://com.lxz.app5/insertstudnet");
ContentValues values=new ContentValues();
values.put("name",editText.getText().toString());
values.put("age",50);
Uri rrui=reserve.insert(uri,values);
System.out.println("插入数据之后的URI"+rrui);
//id为新生成的主键的值
long id=ContentUris.parseId(rrui);
System.out.println(uri.toString()+"---"+(id>=1 ? "插入成功":"插入失败"));
}
//远程查询所有的数据
public void getStudentAll(View view) {
remoteQueryAll();
}
//远程查询指定id的数据
public void getStudentById(View view){
remoteQueryById();
}
//远程模糊查询指定id的数据
public void getStudentByIdVague(View view){
remoteQueryByIdVague();
}
//远程模糊查询指定性别的数据
public void getStudentBySexVague(View view){
remoteQueryBySexVague();
}
//远程删除指定ID的数据
public void deleteStudentById(View view){
remoteDeleteStudnet();
}
//远程更新指定ID的数据
public void updateStudentByName(View view){
remoteUpdateStudnet();
}
//远程插入指定ID的数据
public void insertStudent(View view){
remoteInsertStudnet();
}
}
3)效果图
图1 查询全部数据
图2 查询id=1 的信息
图3 模糊查询id带1的数据
图4 模糊查询年龄带1的
图5 删除id=11的数据
图6 更新id=1的数据的name
图7 插入一条新数据(带监听)
图8 界面图
4)插入的事件监听的设置
(1)app5下的ContentProvider设置监听通知。
- 关键代码:getContext().getContentResolver().notifyChange(uri,null);通知该url上的所有
//插入数据
public Uri insert(@NonNull Uri uri, @Nullable ContentValues contentValues) {
MyHelper helper=new MyHelper(this.getContext(),"studentDB",1);
SQLiteDatabase database=helper.getWritableDatabase();
//遍历的结果
long id=0;
switch (uriMatcher.match(uri)){
case 1:
id =database.insert("student",null,contentValues);
if(id>=1){
//注册监听器,当有新的数据插入的时候去调用
/*
* uri,为在该uri上注册的所有的ContentResover
* */
getContext().getContentResolver().notifyChange(uri,null);
}
break;
default:
throw new RuntimeException("未知uri");
}
database.close();
helper.close();
//为了判断是不是插入成功了,id的值为插入后的主键的号
uri=ContentUris.withAppendedId(uri,id);
return uri;
}
(2)app7创建ContentObserver的子类
/*
* 创建事件监听的类
* */
private class InsertObsever extends ContentObserver {
public InsertObsever(Handler handler) {
super(handler);
}
@Override
public void onChange(boolean selfChange) {
System.out.println("实时查询全部信息");
remoteQueryAll();
}
}
(3)app7下的insert方法注册插入的事件监听。
public void insertObserver(){
Uri uri=Uri.parse("content://com.lxz.app5/insertstudnet");
//注册事件监听
reserve.registerContentObserver(uri,true,new InsertObsever(new Handler()));
}