ContentObserver——内容观察者,目的是观察特定Uri引起的数据库的变化
这个是官方的文档,将的也是比较少
一般使用分为四步,
1、创建内容观察者 ContentObserver
2、注册监听 registerContentObserver
3、刷新数据库改变 onChange
4、注销监听 unregisterContentObserver
下面写2个demo 监听手机的飞行模式,和手机的显示12小时制还是24小时制 对上面的步骤进行说明,可以看下我录制的一个gif图
下面直接上代码了 main 的代码
public class MainActivity extends AppCompatActivity {// 飞行模式的观察者private AirPlaneModeContentObserver airPlaneModeContentObserver;// 12or24小时的观察者private TimeContentObserver timeContentObserver;private TextView airPlaneText;private TextView timeText;@SuppressLint("HandlerLeak")private Handler mHandler = new Handler() {public void handleMessage(Message msg) {switch (msg.what) {case AirPlaneModeContentObserver.MSG_AIRPLANEMODE:int isAirPlaneModeOpen = (Integer) msg.obj;if (isAirPlaneModeOpen == 1) {airPlaneText.setText("已打开");} else {airPlaneText.setText("已关闭");}break;case TimeContentObserver.MSG_TIME_12_24:int is12Or24Hour = (Integer) msg.obj;if (is12Or24Hour == 12) {timeText.setText("12小时制度");} else {timeText.setText("24小时制度");}default:break;}}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);airPlaneText = findViewById(R.id.mode);timeText = findViewById(R.id.time);// 创建观察者airPlaneModeContentObserver = new AirPlaneModeContentObserver(MainActivity.this, mHandler);timeContentObserver = new TimeContentObserver(MainActivity.this, mHandler);findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {startAirPlaneModeRegister();}});findViewById(R.id.btn1).setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {startTimeRegister();}});}private void startTimeRegister() {Uri timeUri = Settings.System.getUriFor(Settings.System.TIME_12_24);Log.e("--------main", "timeUri=" + timeUri);ContentResolver contentResolver = getContentResolver();// 注册contentResolver.registerContentObserver(timeUri, false,timeContentObserver);}private void startAirPlaneModeRegister() {Uri airPlaneModeUri = Settings.System.getUriFor(Settings.System.AIRPLANE_MODE_ON);Log.e("--------main", "airPlaneModeUri=" + airPlaneModeUri);ContentResolver contentResolver = getContentResolver();contentResolver.registerContentObserver(airPlaneModeUri, false, airPlaneModeContentObserver);}@Overrideprotected void onDestroy() {super.onDestroy();getContentResolver().unregisterContentObserver(airPlaneModeContentObserver);getContentResolver().unregisterContentObserver(timeContentObserver);}
}
飞行模式的观察者代码
public class AirPlaneModeContentObserver extends ContentObserver {public static final int MSG_AIRPLANEMODE = 1;private Context mContext;private Handler mHandler;/*** Creates a content observer.** @param handler The handler to run {@link #onChange} on, or null if none.*/public AirPlaneModeContentObserver(Context context, Handler handler) {super(handler);mContext = context;mHandler = handler;}@Overridepublic void onChange(boolean selfChange) {super.onChange(selfChange);try {int isAirPlaneModeOpen = Settings.System.getInt(mContext.getContentResolver(), Settings.System.AIRPLANE_MODE_ON);// 飞行模式为返回值是1,不是飞行模式返回值是0Log.e("------onChange", " isAirPlaneModeOpen=" + isAirPlaneModeOpen);mHandler.obtainMessage(MSG_AIRPLANEMODE, isAirPlaneModeOpen).sendToTarget();} catch (Settings.SettingNotFoundException e) {e.printStackTrace();}}
}
12or24 小时制观察者
public class TimeContentObserver extends ContentObserver {public static final int MSG_TIME_12_24 = 2;private Context mContext;private Handler mHandler;/*** Creates a content observer.** @param handler The handler to run {@link #onChange} on, or null if none.*/public TimeContentObserver(Context context, Handler handler) {super(handler);mContext = context;mHandler = handler;}@Overridepublic void onChange(boolean selfChange) {super.onChange(selfChange);int is12Or24Hour = 0;try {is12Or24Hour = Settings.System.getInt(mContext.getContentResolver(),Settings.System.TIME_12_24);} catch (Settings.SettingNotFoundException e) {e.printStackTrace();}// 12小时制度会返回12 ,24小时制度会返回24 当然我们也可以使用Settings.System.getString()方法Log.e("------onChange", " is12Or24=" + is12Or24Hour);mHandler.obtainMessage(MSG_TIME_12_24, is12Or24Hour).sendToTarget();}
}
代码也是很简单,但是需要特别注意下,并不是我们写前端的注册了 ContentObserver 数据发生变化我们就能接受到的, 想表达的意思就是,假如现在你需要实现一个逻辑,监听接口变化,是显示界面的添加或者删除,
你需要去确保数据源那边发生变化的时候,调用了getContentResolver().notifyChange() 方法了,我们写ContentObserver才会接口到数据变化,否则我们写了ContentObserver onChange 里面也是没有数据返回的.
// 通知已注册的观察者行已更新并尝试同步更改网络
public void notifyChange(@NonNull Uri uri, @Nullable ContentObserver observer) {notifyChange(uri, observer, true /* sync to network */);}
demo 地址,点击跳转到git