提示:本篇文章将会尽量保持精简,附加图文解释,焦躁是敲写代码最大的敌人,三连是最大的支持!
本篇文章将会介绍如何使用 Android studio “内容观察者”,实现 “监测数据变化” 。文章尽量保持精简,并带有图文解释,努力让各位读者拥有更佳的观看体验。项目包括了前篇中的 “内容提供者” 的内容,如果对 “内容提供者” 的项目实施并不是很熟悉,可以先移步到另一篇文章 简单步骤:Android studio 内容提供者 - 实现读取手机通讯录_蛇形刁手的博客-CSDN博客
一、项目介绍
首先在这里不会过多的赘述 “ 内容观察者 ” 的具体知识点,着重介绍如何在 Android studio 中使用 “ 内容观察者 ” 去监测数据库中的数据,因此在该项目中需要创建两个程序去实现项目效果。一个实现对数据库中的数据进行操作,另一个用来监测数据库中的数据是否变化。
二、使用步骤
1.创建第一个程序
创建第一个程序命名为 ContentObserverDB , 指定包名为 com.itcast.contentobserverdb 。
2.导入图片
图片分别命名为 bg.png 和 btn_bg.png (无水印),当然也可使用自己的图片(要注意修改代码中的图片名称)
3.放置界面控件
由于我们要建立一个操作数据库的界面,所以需要在 res/layout 文件夹中的 activity_main.xml 文件中放置四个 Button 按钮控件,分别表示 “添加” 、“更新” 、“删除” 、“查询” 。
代码如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/bg"
android:orientation="vertical">
<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:text="添加"
android:textColor="#006000"
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:text="更新"
android:textColor="#006000"
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:text="删除"
android:textColor="#006000"
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:text="查询"
android:textColor="#006000"
android:textSize="20dp" />
</LinearLayout>
4.创建数据库
显而易见我们要实现监测数据变化,自然要创建一个数据库。所以我们需要在 com.itcast.contentobserverdb 包下新建一个命名为 PersonDBOpenHelper 的java类,来继承 SQLiteOpenHelper 类。
代码如下:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.itcast.contentobserverdb">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.ContentObserverDB">
<provider
android:name=".PersonProvider"
android:authorities="com.itcast.contentobserverdb"
android:enabled="true"
android:exported="true"></provider>
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
5.创建内容提供者
选择程序中的 com.itcast.contentobserverdb 包,单击鼠标右键,选择 【New】-> 【Other】-> 【Content Provide】选项,创建一个内容提供者命名为 PersonProvider 。
代码如下:
package com.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.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("com.itcast.contentobserverdb", "info", SUCCESS);
}
@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 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 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 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("路径不正确,无法更新数据!");
}
}
@Override
public String getType(Uri uri) {
return null;
}
}
6.实现界面交互
对上文中创建的操作界面中的四个 Button 按钮控件在 java/com.itcast.contentobserverdb 文件夹下创建命名为 MainActivity 的Java类中去实现具体操作功能。同时需要注意创建程序后会自动生产一个名为 MainActivity 的 kt 类,这两只是名字相同,不要搞混了。
代码如下:
package com.itcast.contentobserverdb;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
public class MainActivity extends AppCompatActivity implements
View.OnClickListener {
private ContentResolver resolver;
private Uri uri;
private ContentValues values;
private Button btnInsert;
private Button btnUpdate;
private Button btnDelete;
private Button btnSelect;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
createDB();
}
private void initView() {
btnInsert = findViewById(R.id.btn_insert);
btnUpdate = findViewById(R.id.btn_update);
btnDelete = findViewById(R.id.btn_delete);
btnSelect = findViewById(R.id.btn_select);
btnInsert.setOnClickListener(this);
btnUpdate.setOnClickListener(this);
btnDelete.setOnClickListener(this);
btnSelect.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();
}
@Override
public void onClick(View v) {
resolver = getContentResolver();
uri = Uri.parse("content://com.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<Map<String, String>> 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<String, String>();
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;
}
}
}
7.创建第二个程序
创建第二个程序,命名为 MonitorData ,指定包名为 com.itcast.monitordata ,由于我们只需要对数据库的操作进行监测,所以就不需要再有主界面,我们可以直接 java/com.itcast.monitordata 文件夹下创建一个命名为 MainActivity 的java类,来注册一个内容观察者,观察数据库是否发生了变化。
代码如下:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.itcast.monitordata">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.MonitorData">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
8.运行程序
<1>.我们在运行程序时,先回到我们的第一个 ContentObserverDB 程序 打开虚拟机,进行运行。
<2>.然后我们可以打开 Device File Explorer 窗口中(在整个 Android studio 界面的右下角) 根据 【data】->【data】->【com.itcast.contentoberverfb】->【databases】 路径查看系统是否已经生成了 数据库文件 person.db 。
<3>.我们再回到第二个 MonitorData 程序进行运行,然后在 ContentObserverDB 程序界面中分别点击 “添加” 、“更新” 、“删除” 、“查询” 四个按钮,这时界面下方就会出现反馈。
示例效果图:
<4>.最后完成上诉操作后,我们可以点开 Logcat 窗口去查看输出的 Log 信息。
总结
以上就是 Android studio 内容观察者 - 实现数据变化监测的具体操作,由于每个人的配置、编写习惯等等多种原因,如果在实际操作中出现问题,或者发现文章中的错误,也可以在评论区中发表出来,尽能所答,欢迎指点与建议。
编写不易,关注、三连是最大的支持!!!
欢迎建议,感谢支持!!!