zoukankan      html  css  js  c++  java
  • Android-Observer(内容观察者)

    内容提供者应用暴露的数据,是被多个其他应用访问(insert,update,delete,query),但如果L应用要查询(内容提供者应用暴露的数据),难道要开启子线程一直循环去查询 ?

    答:开启子线程一直循环去查询是不合理的(是严重的错误),所以Android提供了Observer(内容观察者)这种机制,当内容提供者里面的数据发送变化(insert, update, delete),就会发出通知,L应用监听到发出的通知,就去查询数据,这样就完美解决了这个问题。

    以下这幅图:把 (监听uri数据的变化:内容观察者ContentObserver)写到了L应用里面,其实是L应用调用ContentResolver.监听uri数据的变化:内容观察者ContentObserver


    S应用--> MyContentProvider 增删改查 代码

    只有 insert,update, delete,能够证明数据发送了改变,所以通过getContext().getContentResolver().notifyChange(uri, null);发出改变通知

    private MySqliteOpenHeper mySqliteOpenHeper;
    
        /**
         * 只要在AndroidManifest.xml中配置了provider组件
         * 应用打开后,会自动启动此方法
         * @return
         */
        @Override
        public boolean onCreate() {
            Log.d(TAG, "onCreate()");
            mySqliteOpenHeper = MySqliteOpenHeper.getInstance(getContext());
            return false;
        }
    
        /**
         * 查询
         * @return
         */
        @Override
        public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
    
            SQLiteDatabase db = mySqliteOpenHeper.getReadableDatabase();
    
            // 查询全部
            Cursor cursor = db.query("cat", // 表名
                    projection, // 查询的列
                    null,   // selection 查询的条件 xxx=?
                    null, // selectionArgs 查询条件的值
                    null, // groupBy 分组
                    null, // having 分组过滤条件
                    "_id desc"); // orderBy 排序 --> 倒序
    
            // 在内容提供者里面,千万不能关闭数据库,关闭游标
    
            return cursor;
        }
    
        /**
         * 增加
         * @return
         */
        @Override
        public Uri insert(Uri uri, ContentValues values) {
            SQLiteDatabase database = mySqliteOpenHeper.getWritableDatabase();
    
            long resultID = database.insert("cat", null, values);
    
            // 在内容提供者里面,千万不能关闭数据库,关闭游标
    
            /**
             * 证明数据发送了改变,所以需要通知其他应用
             * 内容观察者机制: -->发出改变通知给---> 其他应用(内容观察者监听器,监听到发送的改变通知,然后进行查询)
             */
            getContext().getContentResolver().notifyChange(uri, null);
    
            return uri;
        }
    
        /**
         * 修改
         * @return
         */
        @Override
        public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
            SQLiteDatabase database = mySqliteOpenHeper.getWritableDatabase();
    
            // 参数一:表名   参数二:其他应用传递过来的ContentValues   参数三:其他应用传递过来的查询条件
            int updateResult = database.update("cat", values, selection, selectionArgs);
    
            // 在内容提供者里面,千万不能关闭数据库,关闭游标
    
            /**
             * 证明数据发送了改变,所以需要通知其他应用
             * 内容观察者机制: -->发出改变通知给---> 其他应用(内容观察者监听器,监听到发送的改变通知,然后进行查询)
             */
            getContext().getContentResolver().notifyChange(uri, null);
    
            return updateResult;
        }
    
        /**
         * 删除
         * @return
         */
        @Override
        public int delete(Uri uri, String selection, String[] selectionArgs) {
            SQLiteDatabase database = mySqliteOpenHeper.getWritableDatabase();
    
            int deleteResult = database.delete("cat", selection, selectionArgs);
    
            // 在内容提供者里面,千万不能关闭数据库,关闭游标
    
            /**
             * 证明数据发送了改变,所以需要通知其他应用
             * 内容观察者机制: -->发出改变通知给---> 其他应用(内容观察者监听器,监听到发送的改变通知,然后进行查询)
             */
            getContext().getContentResolver().notifyChange(uri, null);
            
            return deleteResult;
        }

    S应用--> AndroidManifest.xml 对外暴露:

        <!--
                MyContentProviderNew是组件需要配置
                可以把MyContentProviderNew看作是服务器
                authorities 看作是服务器 服务器有访问的链接,authorities(授权) ,是唯一标识
                android:enabled="true" 可以被系统实例化
                android:exported="true" 允许对外输出
            -->
            <provider
                android:authorities="autho.prov.cp.MyContentProviderNew"
                android:name=".cp.MyContentProviderNew"
                android:enabled="true"
                android:exported="true"
                />

    L应用 --> NewMainActivity监听发出的改变通知

    package liudeli.cp.client;
    
    import android.app.Activity;
    import android.content.ContentResolver;
    import android.database.ContentObserver;
    import android.net.Uri;
    import android.os.Bundle;
    import android.os.Handler;
    
    public class NewMainActivity extends Activity {
    
        /**
         * 定义ContentResolver
         */
        private ContentResolver contentResolver;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            setContentView(R.layout.activity_main);
    
            // S应用对外暴露的授权标识
            Uri uri = Uri.parse("content://autho.prov.cp.MyContentProviderNew");
    
            contentResolver = getContentResolver();
    
            /**
             * 注册 内容观察者:监听S应用发出的改变通知
             * 参数一:S应用提供的授权
             * 参数二:意思是 是否监 和它表有关系的表 (例如:.../dog   .../dog/#)
             * 参数三:监听器
             *
             * 注册监听: 需要:contentResolver.
             */
            contentResolver.registerContentObserver(uri, true, contentObserver);
        }
    
        /**
         * 监听器:用来监听S应用发出的改变通知
         */
        private ContentObserver contentObserver = new ContentObserver(new Handler()) {
    
            @Override
            public void onChange(boolean selfChange) {
                super.onChange(selfChange);
                /**
                 * 通过contentProvider.query(......) 进行查询S应用数据
                 */
            }
    
            @Override
            public void onChange(boolean selfChange, Uri uri) {
                super.onChange(selfChange, uri);
                /**
                 * 通过contentProvider.query(......) 进行查询S应用数据
                 */
            }
        };
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            /**
             * 解除:内容观察者:监听
             * 解除也需要:contentResolver.
             */
            contentResolver.unregisterContentObserver(contentObserver);
        }
    }

     可以把 内容观察者ContentObserver理解为:广播, 只是代码和广播不一样而已

  • 相关阅读:
    R 包安装问题
    特征值分解与奇异值分解
    向量内积&外积
    hdu_3449(有依赖背包)
    Gene co-expression analysis for functional classification and gene–disease predictions
    MCMC & 贝叶斯
    继承(来自视频)
    面向对象 创建对象
    mongodb笔记(三)
    mongodb笔记(二)
  • 原文地址:https://www.cnblogs.com/android-deli/p/10129601.html
Copyright © 2011-2022 走看看