一、实验目标
- 了解ContentProvider、ContentResolver和ContentObserver之间的联系
- 掌握使用内容提供者对外暴露数据
- 掌握使用ContentResolver操作其他应用的数据
- 掌握使用ContentObserver监视并响应数据变化
二、实验过程
- 创建ContentObserverDB应用,并使用ContentProvider向外共享数据。
创建如下界面
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/bg"
android:orientation="vertical"
tools:context=".MainActivity">
<Button
android:id="@+id/btn_insert"
android:layout_width="120dp"
android:layout_height="40dp"
android:layout_marginLeft="40dp"
android:layout_marginTop="30dp"
android:background="@drawable/btn_bg"
android:textColor="#006000"
android:text="添加"
android:textSize="20dp"/>
<Button
android:id="@+id/btn_update"
android:layout_width="120dp"
android:layout_height="40dp"
android:layout_marginLeft="80dp"
android:layout_marginTop="30dp"
android:background="@drawable/btn_bg"
android:textColor="#006000"
android:text="更新"
android:textSize="20dp"/>
<Button
android:id="@+id/btn_delete"
android:layout_width="120dp"
android:layout_height="40dp"
android:layout_marginLeft="120dp"
android:layout_marginTop="30dp"
android:background="@drawable/btn_bg"
android:textColor="#006000"
android:text="删除"
android:textSize="20dp"/>
<Button
android:id="@+id/btn_select"
android:layout_width="120dp"
android:layout_height="40dp"
android:layout_marginLeft="160dp"
android:layout_marginTop="30dp"
android:background="@drawable/btn_bg"
android:textColor="#006000"
android:text="查询"
android:textSize="20dp"/>
</LinearLayout>
- 接着创建一个Helper类,用来设置数据库。
3.创建ContentProvider
package cn.itcast.contentobserverdb;
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.database.sqlite.SQLiteOpenHelper;
import android.net.Uri;
public class PersonProvider extends ContentProvider {
private static UriMatcher mUriMatcher = new UriMatcher(-1);
private static final int SUCCESS =1;
private PersonDBOpenHelper helper;
static {
mUriMatcher.addURI("cn.itcast.contentobserverdb","info",SUCCESS);
}
public PersonProvider() {
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
int code=mUriMatcher.match(uri);
if(code == SUCCESS){
SQLiteDatabase db=helper.getWritableDatabase();
int count=db.delete("info",selection,selectionArgs);
if(count>0){
getContext().getContentResolver().notifyChange(uri,null);
}
db.close();
return count;
}
else{
throw new IllegalArgumentException("路径不正确,无法随便删除数据!");
}
}
@Override
public String getType(Uri uri) {
// TODO: Implement this to handle requests for the MIME type of the data
// at the given URI.
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public Uri insert(Uri uri, ContentValues values) {
int code=mUriMatcher.match(uri);
if(code == SUCCESS){
SQLiteDatabase db=helper.getReadableDatabase();
long rowId=db.insert("info",null,values);
if(rowId >0){
Uri insertedUri= ContentUris.withAppendedId(uri,rowId);
getContext().getContentResolver().notifyChange(insertedUri,null);
return insertedUri;
}
db.close();
return uri;}
else{
throw new IllegalArgumentException("路径不正确,无法插入数据!");
}
}
@Override
public boolean onCreate() {
helper=new PersonDBOpenHelper(getContext());
return false;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
int code=mUriMatcher.match(uri);
if(code == SUCCESS){
SQLiteDatabase db=helper.getReadableDatabase();
return db.query("info",projection,selection,selectionArgs,null,null,sortOrder);
}else {
throw new IllegalArgumentException("路径不正确,无法查询数据!");
}
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
int code=mUriMatcher.match(uri);
if(code == SUCCESS){
SQLiteDatabase db=helper.getWritableDatabase();
int count=db.update("info",values,selection,selectionArgs);
if(count >0){
getContext().getContentResolver().notifyChange(uri,null);
}
db.close();
return count;
}
else{
throw new IllegalArgumentException("路径不正确,无法更新数据!");
}
}
}
3.在MainActivity中编写按钮逻辑代码
创建数据库,设置点击事件。
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Button mbtn_insert;
private Button mbtn_update;
private Button mbtn_delete;
private Button mbtn_Select;
private ContentResolver resolver;
private Uri uri;
private ContentValues values;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
createDB();
}
private void initView() {
mbtn_insert=(Button)findViewById(R.id.btn_insert);
mbtn_update=(Button)findViewById(R.id.btn_update);
mbtn_delete=(Button)findViewById(R.id.btn_delete);
mbtn_Select=(Button)findViewById(R.id.btn_select);
mbtn_insert.setOnClickListener(this);
mbtn_update.setOnClickListener(this);
mbtn_delete.setOnClickListener(this);
mbtn_Select.setOnClickListener(this);
}
private void createDB() {
PersonDBOpenHelper helper=new PersonDBOpenHelper(this);
SQLiteDatabase db=helper.getWritableDatabase();
for(int i =0;i<3;i++){
ContentValues values=new ContentValues();
values.put("name","itcast"+i);
db.insert("info",null,values);
}
db.close();
}
public void onClick(View v){
resolver=getContentResolver();
uri=Uri.parse("content://cn.itcast.contentobserverdb/info");
values=new ContentValues();
switch (v.getId()){
case R.id.btn_insert:
Random random=new Random();
values.put("name","add_itcast"+random.nextInt(10));
Uri newuri=resolver.insert(uri,values);
Toast.makeText(this,"添加成功",Toast.LENGTH_SHORT).show();
Log.i("数据库应用","添加");
break;
case R.id.btn_delete:
int deleteCount=resolver.delete(uri,"name=?",new String[]{"itcast0"});
Toast.makeText(this,"成功删除了"+deleteCount+"行",Toast.LENGTH_SHORT).show();
Log.i("数据库应用","删除");
break;
case R.id.btn_select:
List data=new ArrayList<Map<String,String>>();
Cursor cursor=resolver.query(uri,new String[]{"_id","name"},null,null,null);
while (cursor.moveToNext()){
Map<String,String> map=new HashMap<>();
map.put("_id",cursor.getString(0));
map.put("name",cursor.getString(1));
data.add(map);
}cursor.close();
Log.i("数据库应用","查询结果:"+data.toString());
break;
case R.id.btn_update:
values.put("name","update_itcast");
int updateCount=resolver.update(uri,values,"name=?",new String[]{"itcast1"});
Toast.makeText(this, "成功更新了"+updateCount+"行", Toast.LENGTH_SHORT).show();
Log.i("数据库应用","更新");
break;
}
}
}
4.创建MonitorData应用,后台运行并监视ContentObserverDB应用中的数据变化,提示数据变化并输出变化后的数据,在Monitor应用界面显示数据。
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Uri uri= Uri.parse("content://cn.itcast.contentobserverdb/info");
getContentResolver().registerContentObserver(uri,true,new Myobserver(new Handler()));
}
private class Myobserver extends ContentObserver{
public Myobserver(Handler handler) {
super(handler);
}
public void onChange(boolean selfChange){
Log.i("监测到数据的变化","有人动了你的数据!");
super.onChange(selfChange);
}
}
protected void onDestroy(){
super.onDestroy();
getContentResolver().unregisterContentObserver(new Myobserver(new Handler()));
}
}
三、实验结果
1,运行ContentobserverDB
找到数据库文件,导出并查看
2.点击运行MonitorData。
由于采用默认界面,所以没有显示。返回ContentObserverDB界面,点击按钮。
返回ContentObserverDB界面。点击按钮
查询tag“数据库应用”
导出数据库并查看
查询tag“监测到数据的变化”
四、实验总结
在本次实验中,了解ContentProvider、ContentResolver和ContentObserver之间的联系,学会了使用内容提供者对外暴露数据,也学会了使用ContentResolver操作其他应用的数据,学习了ContentObserver监视并响应数据变化。