美文网首页
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