Android学习笔记之ContentProvider

2018-10-19  本文已影响0人  sssssss_

1.ContentProvider 内容提供者

1.1ContentProvider 特点

  1. 四大组件之一,需要在 AndroidMainifest.xml 文件中进行注册。
  2. 接口的统一,是为数据的获取、添加、修改的操作提供统一的接口。
  3. 跨进程供多个应用程序共享数据;
  4. 设备存储数据:通讯录、图片;
  5. 数据更新监听:UI更新;

1.2ContentProvider 的优缺点

  1. 数据访问统一接口(存储方式都不用管)优点。
  2. 跨进程数据的访问,优点。
  3. 无法单独使用,必须与其他的存储方式结合使用,缺点。

1.3ContentProvider 如何提供数据,实现共享?

  1. 新建类去继承ContentProvider,然后覆写 query、insert、update、delete 等6个抽象方法。
  2. 必须在 AndroidManifest 文件中进行注册。
  3. 把自己的数据通过 uri 的形式共享出去。
  4. 借助UriMather.match()方法实现匹配内容URI的功能。
  5. 第三方可以通过 ContentResolver 来访问该 Provider。

1.4ContentProvider工作流程

  1. 应用程序A(提供者)定义了 ContentProvider,定义了一些数据库和文件来存放数据。
  2. 应用程序B(访问者)获得 ContentResolver 对象,根据Uri访问指定的 ContentProvider。
  3. ContentProvider 就会访问底层的存储方式,并返回数据给 ContentProvider。
  4. ContentProvider 将数据返回给 ContentResolver,ContentResolver 再转到应用B。

2.ContentResolver 内容访问者

2.1ContentResolver如何实现数据的访问

//简单演示获取数据都代码
Cursor mCursor = getContentResolver().query(uri,projection,selection,selectionArgs,orderBy);
if (mCursor != null) {
     while (mCursor.moveToNext()) {
        String column1 = mCursor.getString(mCursor.getColumnIndex("column1"));
        int column2 = mCursor.getInt(mCursor.getColumnIndex("column2"));
    }
    mCursor.close();
}

3.ContentObserver 内容观察者

Android 内部提供了一种 ContentObserver 来监听数据库内容的变化。作用是观察(捕捉)特定 Uri 引起的数据库的变化,继而做一些相应的处理。

3.1如何定义ContentObserver

//第一步: 创建一个 ContentObserver 的子类,实现 onChange() 方法。
public class MyContentObserver extends ContentObserver{
    private Handler handler;
    public MyContentObserver(Handler handler) {
        super(handler);
        this.handler=handler;
    }
    @Override
    public void onChange(boolean selfChange) {
        super.onChange(selfChange);
        //  在onChange方法里面我们就可以执行变化的操作了
    }
}
//第二步:将这个监听者与我们所要监听的对象绑定
//通过 registerContentObserver 注册 ContentObserver。
MyContentObserver mObserver = new MyContentObserver(); 
getContentResolver().registerContentObserver(Uri uri, boolean notifyForDescendants, ContentObserver observer);
//第三步:取消注册 unregisterContentObserver
getContentResolver().unregisterContentObserver(mObserver)
//ContentProvider数据源发送改变后,通知ContentObserver。
getContext().getContentResolver().notifyChange(uri, null);

3.2也可以这样简单写


public class Main2Activity extends AppCompatActivity {
    Handler mHandler = new Handler() {
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            //在主线程更新UI  adapter.notifyChangeSet();
        }
    };
    ContentObserver observer = new ContentObserver(mHandler) {
        public void onChange(boolean selfChange) {
            super.onChange(selfChange);
            //Uri数据改变,非Ui线程不能直接更新
            //发送消息
        }
    };
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //注册内容观察者
        this.getContentResolver().registerContentObserver(uri, notifyForDescendants, observer);
    }
}

3.3为什么自定义的 ContentProvider 数据源发生改变后,却没有监听到任何反应?

每个ContentProvider数据源发生改变后,如果想通知其监听对象, 例如ContentObserver时,必须在其对应方法 update / insert / delete 时,显式地调用 this.getContentReslover().notifychange(uri,null) 方法,回调监听处理逻辑。否则,我们的 ContentObserver 是不会监听到数据发生改变的。

4.说说ContentProvider、ContentResolver、ContentObserver 之间的关系

5.为什么要用 ContentProvider?它和 sql 的实现上有什么差别?

6.多个进程同时调用一个ContentProvider的query获取数据,ContentPrvoider是如何反应的呢?

尽管ContentResolver与ContentProvider类隐藏了实现细节,ContentProvider除了onCreate()是在UI线程运行,其余所提供的query(),insert(),delete(),update()都是在ContentProvider进程的线程池中被调用执行的,而不是进程的主线程中。因为那些方法可能同时被多个线程所调用,所以他们都应该是线程安全的。这个线程池是由Binder创建和维护的,其实使用的就是每个应用进程中的Binder线程池。

7.你觉得Android设计ContentProvider的目的是什么呢?

  1. 隐藏数据的实现方式,对外提供统一的数据访问接口;
  2. 更好的数据访问权限管理。ContentProvider可以对开发的数据进行权限设置,不同的URI可以对应不同的权限,只有符合权限要求的组件才能访问到ContentProvider的具体操作。
  3. ContentProvider封装了跨进程共享的逻辑,我们只需要Uri即可访问数据。由系统来管理ContentProvider的创建、生命周期及访问的线程分配,简化我们在应用间共享数据(进程间通信)的方式。我们只管通过ContentResolver访问ContentProvider所提示的数据接口,而不需要担心它所在进程是启动还是未启动。

8.运行在主线程的ContentProvider为什么不会影响主线程的UI操作?

上一篇下一篇

猜你喜欢

热点阅读