ContentProvider如何自定义与使用场景是什么?
这道题想考察什么?
  1. 是否了解ContentProvider真实场景使用,是否熟悉ContentProvider使用场景?
考察的知识点
  1. ContentProvider在项目中使用与基本知识
考生应该如何回答
1.请你说下ContentProvider是什么?

答:

ContentProvider是Android提供的一个组件,主要用于实现统一管理和数据共享。这里的数据管理是通过定义统一的访问接口来实现,如增删改查。同时,它采用了类似Internet的URL机制,将数据以URI的形式来区分,这样其他App就可以采用一套标准的URI规范来访问同一处数据,而不用了解具体的实现细节。我们知道在Android系统中可能会涉及到一个App的数据被其他App使用的情况,比如通讯录,日历,短信等,这时就需要一套能实现数据共享的机制,这里的ContentProvider就可以实现此功能,其底层使用了binder来完成App进程之间的交流通信,同时使用匿名共享内存来作为共享数据的实现方法。当然为了保证数据访问的安全性,ContentProvider还对每处的数据URI添加了权限管理机制,以控制该数据的访问者及访问方式。

2.请你描述下如何自定义ContentProvider?

答:

ContentProvider提供了一套通用的数据访问接口:

public class MyContentProvider extends ContentProvider {
    public MyContentProvider() {
    }

    @Override
    public boolean onCreate() {
        // TODO: Implement this to initialize your content provider on startup.
        return false;
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection,
                        String[] selectionArgs, String sortOrder) {
        // TODO: Implement this to handle query requests from clients.
        throw new UnsupportedOperationException("Not yet implemented");
    }

    @Override
    public String getType(Uri uri) {
        // TODO: Implement this to handle requests for the MIME type of the data
        // at the given URI.
        throw new UnsupportedOperationException("Not yet implemented");
    }

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        // TODO: Implement this to handle requests to insert a new row.
        throw new UnsupportedOperationException("Not yet implemented");
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        // Implement this to handle requests to delete one or more rows.
        throw new UnsupportedOperationException("Not yet implemented");
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection,
                      String[] selectionArgs) {
        // TODO: Implement this to handle requests to update one or more rows.
        throw new UnsupportedOperationException("Not yet implemented");
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.

初一看,这些接口跟数据库的访问接口类似。没错,ContentProvider就是特地来管理数据库中的数据的。那么既然作为通用的数据访问接口,ContentProvider为什么没有提供对普通文件的访问接口呢?我觉得是因为普通文件的数据是非结构化的,无法抽象出一套统一的访问接口,而数据库中的数据都是结构化数据,就相对比较简单了。

此外一般我们不会直接运用ContentProvider来访问,而是会通过ContentResolver来访问ContentProvider,是因为ContentProvider作为一个数据源处理中心,不仅仅给App内部使用,还会被其他App访问。所以这里的ContentProvider就好比一个server,其他的App在访问这个ContentProvider的时候都必须先得到一个Server的Client才行,这里的ContentResolver就是Android提供给开发者使用来得到一个ContentProvider Client的管理工具类。示例代码如下:

//根据号码获取联系人的姓名
public void getContactNameByNumber() throws Exception {
    ContentResolver resolver = getContentResolver();
    Cursor cursor = resolver.query(ContactsContract.Contacts.CONTENT_URI, new String[]{ContactsContract.Data.DISPLAY_NAME}, null, null, null);
    if(cursor.moveToFirst()){
        String name = cursor.getString(0);
        Log.i(TAG, name);
    }
    cursor.close();
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.

此外我们在创建一个ContentProvider组件的时候,必须要配置一个authorities,并且必须保证系统内该字段不重名,它就好比URL中的主机地址。示例如下:

<provider
    android:name=".MyContentProvider"
    android:authorities="com.xiaofei"
    android:enabled="true"
    android:exported="true">
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

最后再讲下为何ContentProvider在我们平时开发App中使用的不多?其实,虽然ContentProvider具有数据管理和数据共享的功能,但是大半的优势还是集中在数据共享上,在数据共享的前提下,这个数据管理的优势也才能更加明显。像一些系统内置应用,联系人,日历和短信,就比较合适使用ContentProvider,因为他们经常需要提供数据给其他App。而对于像普通的应用,一般出于安全原因,不会把数据提供给第三方App使用,而在App内部访问数据库的话,完全可以自己实现一套数据库访问框架,因为ContentProvider为了屏蔽数据库的访问细节,本质是在其基础上再封装了一层接口而已,而对于App内部的数据库访问来讲,没有这个必要,而且ContentProvider作为一个组件与系统依赖性较强,相比自己实现一套数据库管理框架,扩展性和灵活性肯定没那么好。当然也有很多第三方开源的数据库框架可用,比如greenDao,ormlite,realm等

3.你对ContentProvider的使用场景能画图举例吗:

答:

【Android组件内核面试题】 ContentProvider如何自定义与使用场景是什么?_android

例如:Android操作系统中,就提供联系人的ContentProvider去暴露联系人的所有数据,我们各个APP引用就可以使用Uri去访问这个联系人ContentProvider暴露出来的数据,有点类似 多个客户端 与 一个服务端的这种关系一样。