美文网首页
Android四大组件-ContentProvide

Android四大组件-ContentProvide

作者: 雷根儿 | 来源:发表于2021-08-17 10:45 被阅读0次

Android四大组件ActivityServiceBroadcastReceiverContentProvide

四、ContentProvide

1.什么是ContentProvide
ContentProvider是Android中提供的专门用于不同应用间数据交互和共享的组件。其本质上是一个标准化的数据管道,它屏蔽了底层的数据管理和服务等细节,以标准化的方式在Android 应用间共享数据、数据交互,跨进程通信。

2.使用方法
1、在当前应用自定义ContentProvider类

  • 继承ContentProvider基类,实现ContentProvide的抽象方法,实现对数据的CRUD(create,retrieve,update,delete),还有onCreate和getType。
  • onCreate(),该方法在ContentProvider创建后会被调用,当其他应用程序第一次访问ContentProvide时,该ContentProvider会被创建出来,并立即回调该onCreate方法
  • getType(Uri uri), 返回 当前Uri所代表的数据的MIME类型。如果该Uri对应数据可能包括多条记录,那么MIME类型字符串应该以 vnd.android.cursor.dir/开头;如果该Uri对应的数据只包含一条记录,那么返回MIME类型字符串应该以vnd.android.cursor.item/开头。
public class MyContentProvide extends ContentProvider {
    //这里的AUTHORITY就是我们在AndroidManifest.xml中配置的authorities
    private static final String AUTHORITY = "com.test.MyProvider";
    //匹配成功后的匹配码
    private static final int MATCH_CODE = 100;
    private static UriMatcher uriMatcher;
    //数据改变后指定通知的Uri
    private static final Uri NOTIFY_URI = Uri.parse("content://" + AUTHORITY );

    static {
        //匹配不成功返回NO_MATCH(-1)
        uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
        //添加我们需要匹配的uri
        uriMatcher.addURI(AUTHORITY,"", MATCH_CODE);
    }
    @Override
    public boolean onCreate() {
        SQLiteDatabase db = this.getContext().openOrCreateDatabase("test_db.db3", Context.MODE_PRIVATE, null);
        db.execSQL("create table tab(_id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL)");
        ContentValues values = new ContentValues();
        values.put("name", "test");
        db.insert("tab", "_id", values);
        db.close();
        return true;
    }

    @Nullable
    @Override
    public Cursor query(@NonNull Uri uri, @Nullable String[] strings, @Nullable String s, @Nullable String[] strings1, @Nullable String s1) {
        int match = uriMatcher.match(uri);
        if (match == MATCH_CODE){
            SQLiteDatabase db = this.getContext().openOrCreateDatabase("test_db.db3", Context.MODE_PRIVATE, null);
            Cursor c = db.query("tab", null, null, null, null, null,null);
            return c;
        }
        return null;
    }

    @Nullable
    @Override
    public String getType(@NonNull Uri uri) {
        return null;
    }

    @Nullable
    @Override
    public Uri insert(@NonNull Uri uri, @Nullable ContentValues contentValues) {
        return null;
    }

    @Override
    public int delete(@NonNull Uri uri, @Nullable String s, @Nullable String[] strings) {
        return 0;
    }

    @Override
    public int update(@NonNull Uri uri, @Nullable ContentValues contentValues, @Nullable String s, @Nullable String[] strings) {
        return 0;
    }
}

2、在AndroidManifest.xml中进行注册

  • 属性name指定ContentProvide实现类的类名;
  • 属性authorities是Uri标识,ContentProvide就是以这个Uri的形式对外提供数据,ContentResolve也是根据该Uri进行访问操作该应用的数据的,可以理解为网站的域名
  • 属性exported指定是否对外暴露数据,只有为true时,其他应用才可以访问该应用的数据,默认值为true。
<provider android:name=".activity.MyContentProvide" android:authorities="com.test.MyProvider"/>

3、其他应用使用ContentResolver对数据进行CRUD操作

  • 通过调用Content的 getContentResolver() 方法获取 ContentResolver对象实例,其实ContentResolver的作用类似于HttpClient,获取对象后就可以根据Uri对应用的数据进行CRUD操作了
public class MyContentResolver extends BaseActivity {
    private ContentResolver resolver;
    private Observer observer;
    @Override
    protected void onCreate(@Nullable @org.jetbrains.annotations.Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //获取ContentResolver对象
        resolver = getContentResolver();
        //获取Uri对象
        Uri uri = Uri.parse("content://com.test.MyProvider");
        //获取数据
        Cursor c = resolver.query(uri, null, null, null, null);
        c.moveToFirst();
        for (int i = 0; i < c.getCount(); i++) {
            int index = c.getColumnIndexOrThrow("name");
            String src = c.getString(index);
            Log.d("TAG", src);
            c.moveToNext();
        }
        //注册ContentObserver监听数据的变化
        observer = new Observer(new Handler());
        resolver.registerContentObserver(uri, true,observer);
    }
    class Observer extends ContentObserver {

        public Observer(Handler handler) {
            super(handler);
        }

        @Override
        public void onChange(boolean selfChange) {
            super.onChange(selfChange);
            Toast.makeText(MyContentResolver.this,
                    "数据列表发生变化", Toast.LENGTH_SHORT).show();
            //onchange 方法中添加Toast便于观察
        }
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        resolver.unregisterContentObserver(observer);
    }
}

3.其他相关类

  • Uri(Universal Resource Identifier)统一资源定位符
    ContentResolver通过uri来定位自己要访问的数据,安卓隐式启动的过程中我们也是通过uri来定位我们需要打开的Activity并且可以在uri中传递参数
    URI的格式如下:[scheme:][//host:port][path][?query]
    单单看这个可能我们并不知道是什么意思,下面来举个栗子就一目了然了
    URI:http://www.baidu.com:8080/wenku/jiatiao.html?id=123456&name=jack
    scheme:根据格式我们很容易看出来scheme为http
    host:www.baidu.com
    port:就是主机名后面path前面的部分为8080
    path:在port后面?的前面为wenku/jiatiao.html
    query:?之后的都是query部分为 id=123456$name=jack
    uri的各个部分在安卓中都是可以通过代码获取的,下面我们就以上面这个uri为例来说下获取各个部分的方法:
    getScheme() :获取Uri中的scheme字符串部分,在这里是http
    getHost():获取Authority中的Host字符串,即 www.baidu.com
    getPost():获取Authority中的Port字符串,即 8080
    getPath():获取Uri中path部分,即 wenku/jiatiao.html
    getQuery():获取Uri中的query部分,即 id=15&name=du

  • UriMatcher在ContentProvider 中注册URI,根据 URI 匹配 ContentProvider 中对应的数据表
    该类主要提供了如下两个方法:
    ① public void addURI(String authority, String path, int code) 用于向UriMatcher注册Uri,其中参数authority与path组成一个Uri,参数code 是该Uri对应的标识码
    ② public int match(Uri uri) 根据前面注册的Uri返回其对应的标识码,如果在UriMatcher中找不到对应的Uri则返回-1

  • ContentObserver观察 Uri引起 ContentProvider 中的数据变化 & 通知外界(即访问该数据访问者)
    1、继承 ContentObserver 实现 onChange方法
    2、注册ContentObserver 内容观察者 registerContentObserver
    3、当该URI的ContentProvider数据发生变化时,通知外界getContext().getContentResolver().notifyChange(uri, null);
    4、解除观察者 getContentResolver().unregisterContentObserver(uri)。

4.应用场景

  • 可以使用系统自带的ContentProvider,如音频、视频、图片、通讯录和短信
  • 单一应用的数据存储,但一般情况是跨进程使用
  • 多应用开发数据共享

相关文章

网友评论

      本文标题:Android四大组件-ContentProvide

      本文链接:https://www.haomeiwen.com/subject/ndembltx.html