ContentObserver -- 内容观察者, 目的是观察(捕捉)特定Uri 引起的数据库的变化,继而做一些相应的处理。
它类似于数据库技术中的触发器(Trigger),当ContentObserver所观察的Uri发生变化时,便会触发它。触发器分为表触发器、行触发器,相应地ContentObserver也分为“表“ContentObserver、“行”ContentObserver,当然这是与它所监听的Uri MIME Type有关的。
一、使用ContentObserver来观察蓝牙打开和关闭状态的步骤
1. 创建一个子类,继承ContentObserver;
2. 在此子类中重写 onChange() 方法;
3. 根据Uri 来注册内容观察者。
具体步骤如下所示:
1. 创建一个子类,继承ContentObserver。
/** * 用于观察 sysem 中的 手电筒是否打开或者关闭 * Created by czj on 2016/12/2. */ public class BluetoothObserver extends ContentObserver { private Context mContext; private Handler mHandler; private static final int MSG_BLUETOOTH_ON = 3; /** * Creates a content observer. * * @param handler The handler to run {@link #onChange} on, or null if none. */ public BluetoothObserver(Context context, Handler handler) { super(handler); mContext = context; mHandler = handler; Log.e("TAG", "FlashlightObserver: " ); } @Override public void onChange(boolean selfChange) { Log.e("TAG", "FlashlightObserver onChange" ); try { int bluetoothOn = Settings.System.getInt(mContext.getContentResolver(), Settings.Global.BLUETOOTH_ON); mHandler.obtainMessage(MSG_BLUETOOTH_ON,bluetoothOn).sendToTarget(); } catch (Settings.SettingNotFoundException e) { e.printStackTrace(); } } } 3. 根据Uri 来注册内容观察者。
public class MainActivity extends AppCompatActivity { private static final String TAG = "MainActivity"; private TextView tvAirplane; //Message 类型值 private static final int MSG_FLASHLIGHT_ON = 3; private BluetoothObserver bluetoothObserver; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tvAirplane = (TextView) findViewById(R.id.tvAirplane); bluetoothObserver = new BluetoothObserver(this, mHandler); //注册内容观察者 registerContentObservers(); } private void registerContentObservers() { Uri flashlightUri = Settings.System.getUriFor(Settings.System.BLUETOOTH_ON); getContentResolver().registerContentObserver(flashlightUri, false, bluetoothObserver); } private Handler mHandler = new Handler(){ @Override public void handleMessage(Message msg) { Log.e("TAG", "handleMessage" + msg.what); switch (msg.what){ case MSG_FLASHLIGHT_ON: int isFlashlightOpen = (int) msg.obj; if (isFlashlightOpen == 0){ tvAirplane.setText("蓝牙关闭"); }else{ tvAirplane.setText("蓝牙打开"); } break; } } }; } xml 文件
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" app:layout_behavior="@string/appbar_scrolling_view_behavior" tools:context="com.example.zhengjunchen.observerdemo.MainActivity" tools:showIn="@layout/activity_main"> <TextView android:id="@+id/tvAirplane" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!"/> <EditText android:id="@+id/smsoutboxContent" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </LinearLayout>
注册/取消注册ContentObserver方法,抽象类ContentResolver类中的方法原型如下:
public final void registerContentObserver(Uri uri, boolean notifyForDescendents, ContentObserver observer)
功能:为指定的Uri注册一个ContentObserver派生类实例,当给定的Uri发生改变时,回调该实例对象去处理。
参数:uri 需要观察的Uri(需要在UriMatcher里注册,否则该Uri也没有意义了)
notifyForDescendents 为false 表示精确匹配,即只匹配该Uri
为true 表示可以同时匹配其派生的Uri,举例如下:
假设UriMatcher 里注册的Uri共有一下类型:
1 、content://com.qin.cb/student (学生)
2 、content://com.qin.cb/student/#
3、 content://com.qin.cb/student/schoolchild(小学生,派生的Uri)
假设我们当前需要观察的Uri为content://com.qin.cb/student,如果发生数据变化的 Uri 为
content://com.qin.cb/student/schoolchild ,当notifyForDescendents为 false,那么该ContentObserver会监听不到,
但是当notifyForDescendents 为ture,能捕捉该Uri的数据库变化。
observer ContentObserver的派生类实例
public final void unregisterContentObserver(ContentObserver observer)
功能:取消对给定Uri的观察
参数: observer ContentObserver的派生类实例
ContentObserver类介绍
构造方法 public void ContentObserver(Handler handler)
说明:所有 ContentObserver的派生类都需要调用该构造方法
参数: handler Handler对象。可以是主线程Handler(这时候可以更新UI 了),也可以是任何Handler对象。
常用方法
void onChange(boolean selfChange)
功能:当观察到的Uri发生变化时,回调该方法去处理。所有ContentObserver的派生类都需要重载该方法去处理逻辑。
参数:selfChange 回调后,其值一般为false,该参数意义不大(我也不懂,理解方法最重要)。
另外两个方法,用处不大,我也不懂,大家参照SDK自行理解,冒昧了。
boolean deliverSelfNotifications()
说明:Returns true if this observer is interested in notifications for changes made through the cursor the observer is registered with.
final void dispatchChange(boolean selfChange)
观察特定Uri的步骤如下:
1、 创建我们特定的ContentObserver派生类,必须重载父类构造方法,必须重载onChange()方法去处理回调后的功能实现
2、 利用context.getContentResolover()获得ContentResolove对象,接着调用registerContentObserver()方法去注册内容观察者
3、 由于ContentObserver的生命周期不同步于Activity和Service等,因此,在不需要时,需要手动的调用
unregisterContentObserver()去取消注册。