二、SharedPreferences 之 OnSharedPreferenceChangeListener()
三、ContentProvider 之 ContentObserver
五、Flutter 数据监听之 ChangeNotifier
日常Android开发中总会遇到数据变化监听的需求,譬如一个数据变化需要多个页面或者activity内容同时更新。 而Android中通知数据变化的方式有多种,具体使用哪种需要根据具体情况而定。
一、Broadcast之BroadcastReciever
顾名思义,这类数据变化的监听过程是,数据变化-> 发送广播->接收广播->处理广播
具体使用方法如下:
1、数据变化时发送广播
Intent intent = new Intent(“android.action..ZZZZZZZ”);
intent.putExtra("data", “zzzzzzz”);
mContext.sendBroadcast(intent);
2、数据使用方要注册receiver
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(“android.action..ZZZZZZZ”)) {
///ZZZZZ
}
}
};
registerReceiver(mReceiver, new IntentFilter( “android.action..ZZZZZZZ”));
3、退出时要注销reciever
unregisterReceiver(mReceiver);
二、SharedPreferences 之 OnSharedPreferenceChangeListener()
SharedPreference 是一种简单的数值存储模式,实际上是存在一个 设备安装目录的shared_prefs路径下面的xml文件里
当文件内容变化时, 会回调 OnSharedPreferenceChangeListener()
1、通常情况下可能会这样写
PreferenceManager.getDefaultSharedPreferences(getApplicationContext())
.registerOnSharedPreferenceChangeListener(new OnSharedPreferenceChangeListener() {
@Override
public void onSharedPreferenceChanged(
SharedPreferences sharedPreferences, String key) {
Log.i(LOGTAG, "testOnSharedPreferenceChangedWrong key =" + key);
}
});
2、但是这种方法因为弱引用的关系,一旦被垃圾回收回调就不会被调用
private final WeakHashMap<OnSharedPreferenceChangeListener, Object> mListeners =
new WeakHashMap<OnSharedPreferenceChangeListener, Object>();
//some code goes here
public void More ...registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) {
synchronized(this) {
mListeners.put(listener, mContent);
}
}
3、正确的解决方法是,在onResume里注册回调,在onPause里注销回调
@Override
protected void onResume() {
super.onResume(); getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(mOnSharedPreferenceChangeListener);
}
@Override
protected void onPause() {
super.onPause();
getPreferenceScreen().getSharedPreferences()
.unregisterOnSharedPreferenceChangeListener(mOnSharedPreferenceChangeListener);
}
但是这个监听只能当前正在显示的activity里有效,其他activity里依然监听不到数据变化,因为其他activity处于onPause状态
三、ContentProvider 之 ContentObserver
通常情况下当android本地数据库发生变化时,会发出通知,然后对应的contentObserver 接收通知,并重新读取数据更新UI.
1、定义contentURI
public static final Uri CONTENT_URI = Uri.parse("content://ZZZZZZZZZ");
2、当对应数据库发生变化时,发出通知
context.getContentResolver().notifyChange(CONTENT_URI, null);
3、数据库使用方注册contentObserver
context.getApplicationContext().getContentResolver().registerContentObserver(CONTENT_URI, true, mContentObserver);
private ContentObserver mContentObserver = new ContentObserver(mHandler) {
@Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
/ZZZZZZZZZZZZZZZZZZZ }
};
上面三种是使用java 代码框架时的三种方式,下面两种是Flutter/dart 代码框架的两种数据监听方式
四、Flutter 数据监听之 EventBus
在flutter开发中经常会遇到子widget传递消息给父widget的场景,这时需要类似通知或者广播的方法,EventBus就是解决这类问题的。
具体使用方法如下:
1、封装一个eventBus 事件总线的文件
// 引入 eventBus 包文件
import 'package:event_bus/event_bus.dart';
// 创建EventBus
EventBus eventBus = new EventBus();
// event 监听
class EventFn{
// 想要接收的数据时什么类型的,就定义相同类型的变量
final bool msg;
EventFn(this.msg);
}
2、需要发送事件的文件中利用 eventBus.fire 发送事件
//引入封装的e vent_bus.dart 文件
import 'package:new_flutter/utils/event_bus.dart';
//数据发生变化后, 调用 eventBus.fire 发送事件信息,通知监听方
eventBus.fire(EventFn({
false
}));
3、在需要监听的文件中,利用 eventBus.on< >().listen() 监听信息
// 注册监听器,订阅 eventbus
var eventBusFn = eventBus.on<EventFn>().listen((event) {
// event.msg 就是传过来的监听数据
});
4、 在组件销毁时,一定要销毁监听,防止内存泄漏
@override
void dispose() {
super.dispose();
//取消订阅
eventBusFn.cancel();
}
五、Flutter 数据监听之 ChangeNotifier
Flutter 真正直接监听数据变化的是ChangeNotifier,使用者只要addListener就行了,
具体使用方法如下:
1、封装一个ChangeNotifier
class YkqInfo extends ChangeNotifier{
//要监控的数据类型,想定义什么类型就定义什么类型
static String ykqQr = "";
static YkqInfo _instance;
static YkqInfo getInstance(){
if(_instance == null) {
_instance = new YkqInfo();
}
return _instance;
}
setYkqUrl(String qrUrl){
ykqQr = qrUrl;
//通知监听方数据更新
notifyListeners();
}
}
2、数据变化时,刷新ChangeNotifier里的数据
YkqInfo.getInstance().setYkqUrl(qrUrl);
3、数据监听方addListener,并实时回调刷新
YkqInfo.getInstance().addListener(() {
// 监听数据发生变化并处理
//有必要的话进行UI页面刷新
setState(() {
});
});