在开发 Android 应用程序时,我们经常会使用数据库来存储应用的数据。而随着应用程序的运行,数据也会不断地改变。如果我们能够实现对数据库变化的实时监听,就可以在数据变化时做出相应的操作,提高应用程序的运行效率和用户体验。
Android 提供了 SQLite 数据库作为默认的数据库引擎,并且支持 ContentProvider 来对数据库进行封装和管理。在这种情况下,Android 提供了两种方式来实现对数据库变化的监听:ContentObserver 和 BroadcastReceiver。
一、ContentObserver
ContentObserver 是一个用于观察 ContentProvider 的变化的观察者。我们可以使用它来监听数据库的变化,并做出相应的操作。
使用 ContentObserver 需要继承它,并重写onChange() 方法。在这个方法里面,我们可以获取到发生变化的 Uri,并根据 Uri 来做出不同的操作。下面是一个简单的例子:
“`
public class MyContentObserver extends ContentObserver {
private Context mContext;
public MyContentObserver(Context context) {
super(null);
mContext = context;
}
@Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
// 处理数据库变化的逻辑
}
@Override
public void onChange(boolean selfChange, Uri uri) {
super.onChange(selfChange, uri);
if (uri.equals(MyContentProvider.URI_STUDENTS)) {
// 处理学生表的变化
} else if (uri.equals(MyContentProvider.URI_TEACHERS)) {
// 处理教师表的变化
} else {
// 其他表的变化
}
}
}
“`
在这个例子中,我们继承了 ContentObserver,并在 onChange() 方法里面获取到了数据库变化的 Uri。然后根据 Uri 来做出相应的操作。需要注意的是,我们可以在构造方法中传入 null,因为这个参数在这个例子中并没有用到。
在使用 ContentObserver 时,我们还需要使用 ContentResolver 注册 ContentObserver 对象,并绑定监听的 Uri。
“`
MyContentObserver observer = new MyContentObserver(mContext);
mContext.getContentResolver().registerContentObserver(MyContentProvider.URI_STUDENTS, true, observer);
“`
在这个例子中,我们注册了一个 ContentObserver 对象,用来监听学生表的变化。
二、BroadcastReceiver
除了使用 ContentObserver,我们还可以使用 BroadcastReceiver 来监听数据库的变化。BroadcastReceiver 是 Android 提供的一种可以接收广播消息的组件。我们可以通过广播消息来实现数据的通知和同步等功能。
在 Android 中,有两种方式可以实现数据库的广播通知:Intent.ACTION_PROVIDER_CHANGED 和自定义广播消息。
1. 使用 Intent.ACTION_PROVIDER_CHANGED
Intent.ACTION_PROVIDER_CHANGED 是一个系统定义的广播消息,用于通知 ContentProvider 的变化。我们可以在 BroadcastReceiver 中通过 IntentFilter 来匹配这个广播消息,并在 onReceive() 方法中对广播消息进行处理。
下面是一个简单的例子:
“`
public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (Intent.ACTION_PROVIDER_CHANGED.equals(action)) {
Uri uri = intent.getData();
if (uri.equals(MyContentProvider.URI_STUDENTS)) {
// 处理学生表的变化
} else if (uri.equals(MyContentProvider.URI_TEACHERS)) {
// 处理教师表的变化
} else {
// 其他表的变化
}
}
}
}
“`
在这个例子中,我们继承了 BroadcastReceiver,并在 onReceive() 方法中,根据收到的广播消息来做出相应的操作。需要注意的是,我们在广播消息中传递的是一个 Uri 对象,而不是 ContentObserver 中的 UriMatcher。
在使用 BroadcastReceiver 时,我们需要在 AndroidManifest.xml 中注册这个组件,并设置相应的 IntentFilter。
“`
“`
在这个例子中,我们注册了一个 BroadcastReceiver,用来监听我们自定义的 ContentProvider 的变化。需要注意的是,我们需要设置相应的 scheme 和 host,以匹配我们的 ContentProvider。
2. 自定义广播消息
除了使用系统定义的广播消息,我们还可以自定义广播消息来实现数据库变化的监听。我们可以在 ContentProvider 中发送自定义广播消息,并在 BroadcastReceiver 中通过注册相应的 IntentFilter 来监听这些消息。
下面是一个简单的例子:
“`
public class MyContentProvider extends ContentProvider {
public static final String ACTION_STUDENTS_CHANGED = “com.example.mycontentprovider.students_changed”;
public static final String ACTION_TEACHERS_CHANGED = “com.example.mycontentprovider.teachers_changed”;
public static final Uri URI_STUDENTS = Uri.parse(“content://com.example.mycontentprovider/students”);
public static final Uri URI_TEACHERS = Uri.parse(“content://com.example.mycontentprovider/teachers”);
@Override
public boolean onCreate() {
// 初始化数据库
return true;
}
@Nullable
@Override
public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
// 查询数据
return null;
}
@Nullable
@Override
public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
// 插入数据
notifyChanged(uri);
return null;
}
@Override
public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {
// 更新数据
notifyChanged(uri);
return 0;
}
@Override
public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
// 删除数据
notifyChanged(uri);
return 0;
}
@Nullable
@Override
public String getType(@NonNull Uri uri) {
return null;
}
private void notifyChanged(Uri uri) {
String action = null;
if (uri.equals(URI_STUDENTS)) {
action = ACTION_STUDENTS_CHANGED;
} else if (uri.equals(URI_TEACHERS)) {
action = ACTION_TEACHERS_CHANGED;
}
if (action != null) {
getContext().sendBroadcast(new Intent(action));
}
}
}
“`
在这个例子中,我们在 insert()、update() 和 delete() 方法里面,发送了自定义的广播消息。这些消息分别对应了学生表和教师表的变化。在发送广播消息时,我们使用了 Android 的 Context 类来获取到一个广播的发送器,并通过 Intent 来传递广播消息。
在上面的代码中,我们使用了一个名为 notifyChanged() 的方法来发送广播消息。这个方法的作用是根据传入的 Uri 判断要发送哪种类型的广播消息。在这个方法里面,我们创建了一个新的 Intent,并调用了 sendBroadcast() 方法来发送广播消息。这个方法会将广播消息发送到所有已经注册了相应 IntentFilter 的 BroadcastReceiver。
在使用自定义广播消息时,我们还需要在 BroadcastReceiver 中注册 IntentFilter,并监听相应的广播消息。
“`
public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (MyContentProvider.ACTION_STUDENTS_CHANGED.equals(action)) {
// 处理学生表的变化
} else if (MyContentProvider.ACTION_TEACHERS_CHANGED.equals(action)) {
// 处理教师表的变化
} else {
// 其他消息的处理
}
}
}
“`
在这个例子中,我们注册了一个 BroadcastReceiver,并设置相应的 IntentFilter,以监听我们发送的广播消息。
“`
“`
需要注意的是,我们在 IntentFilter 中设置的是可以匹配上我们发送的广播消息的唯一标识符,而不是发送的 Uri。
ContentObserver 和 BroadcastReceiver 都是 Android 提供的用于监听数据库变化的方式。我们可以根据自己的需求选择适合自己的方式。在使用 ContentObserver 时,我们需要使用 ContentResolver 注册 ContentObserver 对象,并绑定监听的 Uri。在使用 BroadcastReceiver 时,我们需要在 AndroidManifest.xml 中注册 BroadcastReceiver,并设置相应的 IntentFilter。无论我们选择哪种方式,都可以实现对数据库变化的监听,并做出相应的操作。
相关问题拓展阅读:
- android 怎么解决反复监听ContentObserver的问题
- android源码中有launcher2launcher3,用的是哪个
android 怎么解决反复监听ContentObserver的问题
我也遇到了
最新来的短信,应该是未读的,你可以在onChange()里,判断之一条是不扒数是有未读标志,是的话,悔此宏再删除呀碧册!
直接判断短信日期就行了 只删除最新的一条
期待大牛答案{in:}
高手们快来回答。。。。
android源码中有launcher2launcher3,用的是哪个
1、Launcher进程启动过程
可以由下面图看到Launcher进程是如何被创建启动:
Activity Manager通过发送Intend来启动Launcher。
Intent intent = new Intent(mTopAction, mTopData != null ?
Uri.parse(mTopData) : null);
intent.setComponent(mTopComponent);
if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL)
{
intent.addCategory(Intent.CATEGORY_HOME);
}
startActivityLocked(null, intent, null, null, 0, aInfo,
null, null, 0, 0, 0, false, false);
复制代码
因此,如果你要开机启动一个替换Launcher的程序,只要在程序里面加入action.MAIN 、
category.HOME、category.DEFAULT就可以。如果出现多个程序穗野老都加入这种intent,系统会弹出让你选择
哪个作为启动器。
2、Launcher初始化——LauncherApplication。
Application类,我想大部分做Android应用的朋友都用过,每个Android应用默认都有一个Application类,
你也可以继承Application类,然后加入自己代码。Application是一个全局的应用类,在AndroidManifest.xml
我们也可以找到Application标签。
复制代码
Android四大组件的声明都需要放到application标签里面,默认使用的是系统的Application类,如果你在项目里面重载了脊轮它。就需要在标签,name属性下写上你的新的Application类名。Launcher里面就是继承了Application为LauncherApplication。应用启动的时候首先会加载Application。我们可以看到Launcher主类Launcher.java的onCreate函数里面,之一个就是获取Application的实例。
LauncherApplication app = ((LauncherApplication)getApplication());
复制代码
接下来我们看看LauncherApplication里面初始化,LauncherApplication大部分工作就是在初始化完成,剩下都是一些返回接口。
@Override
public void onCreate()
{
super.onCreate();
//获取屏幕大小,主要用来区分手机还是平板
final int screenSize = getResources().getConfiguration().screenLayout &
Configuration.SCREENLAYOUT_SIZE_MASK;
sIsScreenLarge = screenSize == Configuration.SCREENLAYOUT_SIZE_LARGE ||
screenSize == Configuration.SCREENLAYOUT_SIZE_XLARGE;
//屏幕密度
sScreenDensity = getResources().getDisplayMetrics().density;
//IconCahe里面保存了界面所有应用图标的绘画需要的数据,这个到时候具体分析再说。
//加入这东西的主要原因是为了提高绘画界面的效率
mIconCache = new IconCache(this);
//数据库加载类,LauncherModel是Launcher里面非常重要的一个类,相当于MVC模式里面的
//Model功能,管理数据和初始化数据
mModel = new LauncherModel(this, mIconCache);
//下面注册了一些监听器,主要包含APK文件更新删除等数据变化的时候接收的通知
//接收通知后,主要是用来更新Launcher里面的数据库。因为桌面应用图标数据,只会加载一次
IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
filter.addDataScheme(“package”);
registerReceiver(mModel, filter);
filter = new IntentFilter();
filter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
filter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
filter.addAction(Intent.ACTION_LOCALE_CHANGED);
filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
registerReceiver(mModel, filter);
filter = new IntentFilter();
filter.addAction(SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED);
registerReceiver(mModel, filter);
filter = new IntentFilter();
filter.addAction(SearchManager.INTENT_ACTION_SEARCHABLES_CHANGED);
registerReceiver(mModel, filter);
//contentresolver则是用于管理所有程序的contentprovider实例
ContentResolver resolver = getContentResolver();
//注册内容观察者,监听application数据库变化,回调
resolver.registerContentObserver(LauncherSettings.Favorites.CONTENT_URI, true, mFavoritesObserver);
}
复制代码
上面是LauncherApplication最主要的工作,初始化整个Launcher的一些关键类,和注册一些监听器。主要都是用来监听应用的安装更新删除等导致Launcher数据库变化的操作。Launcher数据都是使用contentprovider来提供数据。其中注册的监听接口是
private final ContentObserver mFavoritesObserver = new ContentObserver(new Handler())
{
@Override
public void onChange(boolean selfChange)
{
//重新加载界面数据
mModel.startLoader(LauncherApplication.this, false);
}
};
复制代码
LauncherSettings.Favorites.CONTENT_URI里面数据发生变化的时候,都会调用mModel.startLoader()接口,
重新加载Launcher的数据。startLoader的具体操作,我后面分析LauncherModel类的时候会分析。这一块涉及
Launcher所有数据加载。剩下的接都是返回初始化时候创建的对象或者获取屏幕密度、获取是否大屏幕。
后面很多处理都需要判断是否是大屏幕,4.0以后手机平板都共用一套系统,导致多了很多处理。 3、Launcher.java初始化Launcher.java是Launcher里面最主要的类,是一个Activity。启动的之一个组件。既然是Activity,我们要分析它初始化,毫无疑问,需要找到onCreate()里面分析。把主要一些分析用注释方式写在代码里面,这样比较方便阅读。
关于android 监听数据库变化的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。