• ContentObserver的使用完整详细示例


    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
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    package cn.testcontentprovider;
    import android.content.ContentProvider;
    import android.content.ContentUris;
    import android.content.ContentValues;
    import android.content.UriMatcher;
    import android.database.Cursor;
    import android.database.sqlite.SQLiteDatabase;
    import android.net.Uri;
    /**
     * Demo描述:
     * 自定义ContentProvider的实现
     * ContentProvider主要用于在不同的应用程序之间共享数据,这也是官方推荐的方式.
     *
     * 注意事项:
     * 1 在AndroidManifest.xml中注册ContentProvider时的属性
     *   android:exported=true表示允许其他应用访问.
     * 2 注意*和#这两个符号在Uri中的作用
     *   其中*表示匹配任意长度的字符
     *   其中#表示匹配任意长度的数据
     *   所以:
     *   一个能匹配所有表的Uri可以写成:
     *   一个能匹配person表中任意一行的Uri可以写成:
     *  
     */
    public class ContentProviderTest extends ContentProvider {
        private SQLiteDatabaseOpenHelper mSQLiteDatabaseOpenHelper;
        private final static String  AUTHORITY=cn.bs.testcontentprovider;
        private  static UriMatcher mUriMatcher;
        private static final int PERSON_DIR = 0;
        private static final int PERSON = 1;
         
        /**
         * 利用静态代码块初始化UriMatcher
         * 在UriMatcher中包含了多个Uri,每个Uri代表一种操作
         * 当调用UriMatcher.match(Uri uri)方法时就会返回该uri对应的code;
         * 比如此处的PERSONS和PERSON
         */
        static {
            mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
            // 该URI表示返回所有的person,其中PERSONS为该特定Uri的标识码
            mUriMatcher.addURI(AUTHORITY, person, PERSON_DIR);
            // 该URI表示返回某一个person,其中PERSON为该特定Uri的标识码
            mUriMatcher.addURI(AUTHORITY, person/#, PERSON);
        }
         
         
        /**
         * 在自定义ContentProvider中必须覆写getType(Uri uri)方法.
         * 该方法用于获取Uri对象所对应的MIME类型.
         *
         * 一个Uri对应的MIME字符串遵守以下三点:
         * 1  必须以vnd开头
         * 2  如果该Uri对应的数据可能包含多条记录,那么返回字符串应该以vnd.android.cursor.dir/开头
         * 3  如果该Uri对应的数据只包含一条记录,那么返回字符串应该以vnd.android.cursor.item/开头
         */
        @Override
        public String getType(Uri uri) {
            switch (mUriMatcher.match(uri)) {
            case PERSON_DIR:
                return vnd.android.cursor.dir/+AUTHORITY+.persons;
            case PERSON:
                return vnd.android.cursor.item/+AUTHORITY+.person;
            default:
                throw new IllegalArgumentException(unknown uri+uri.toString());
            }
        }  
     
         
        @Override
        public boolean onCreate() {
            mSQLiteDatabaseOpenHelper=new SQLiteDatabaseOpenHelper(getContext());
            return true;
        }
         
     
        /**
         * 插入操作:
         * 插入操作只有一种可能:向一张表中插入
         * 返回结果为新增记录对应的Uri
         * 方法db.insert()返回结果为新增记录对应的主键值
         */
        @Override
        public Uri insert(Uri uri, ContentValues values) {
            SQLiteDatabase db = mSQLiteDatabaseOpenHelper.getWritableDatabase();
            switch (mUriMatcher.match(uri)) {
            case PERSON_DIR:
                long newId = db.insert(person, name,phone,salary, values);
                //向外界通知该ContentProvider里的数据发生了变化 ,以便ContentObserver作出相应
                getContext().getContentResolver().notifyChange(uri, null); 
                return ContentUris.withAppendedId(uri, newId);
            default:
                throw new IllegalArgumentException(unknown uri + uri.toString());
            }
        }
         
        /**
         * 更新操作:
         * 更新操作有两种可能:更新一张表或者更新某条数据
         * 在更新某条数据时原理类似于查询某条数据,见下.
         */
        @Override
        public int update(Uri uri, ContentValues values, String selection,String[] selectionArgs) {
            SQLiteDatabase db = mSQLiteDatabaseOpenHelper.getWritableDatabase();
            int updatedNum = 0;
            switch (mUriMatcher.match(uri)) {
            // 更新表
            case PERSON_DIR:
                updatedNum = db.update(person, values, selection, selectionArgs);
                break;
            // 按照id更新某条数据
            case PERSON:
                long id = ContentUris.parseId(uri);
                String where = personid= + id;
                if (selection != null && !.equals(selection.trim())) {
                    where = selection +  and  + where;
                }
                updatedNum = db.update(person, values, where, selectionArgs);
                break;
            default:
                throw new IllegalArgumentException(unknown uri + uri.toString());
            }
            //向外界通知该ContentProvider里的数据发生了变化 ,以便ContentObserver作出相应
            getContext().getContentResolver().notifyChange(uri, null); 
            return updatedNum;
        }
         
        /**
         * 删除操作:
         * 删除操作有两种可能:删除一张表或者删除某条数据
         * 在删除某条数据时原理类似于查询某条数据,见下.
         */
        @Override
        public int delete(Uri uri, String selection, String[] selectionArgs) {
            SQLiteDatabase db = mSQLiteDatabaseOpenHelper.getWritableDatabase();
            int deletedNum = 0;
            switch (mUriMatcher.match(uri)) {
            // 删除表
            case PERSON_DIR:
                deletedNum = db.delete(person, selection, selectionArgs);
                break;
            // 按照id删除某条数据
            case PERSON:
                long id = ContentUris.parseId(uri);
                String where = personid= + id;
                if (selection != null && !.equals(selection.trim())) {
                    where = selection +  and  + where;
                }
                deletedNum = db.delete(person, where, selectionArgs);
                break;
            default:
                throw new IllegalArgumentException(unknown uri + uri.toString());
            }
            //向外界通知该ContentProvider里的数据发生了变化 ,以便ContentObserver作出相应
            getContext().getContentResolver().notifyChange(uri, null); 
            return deletedNum;
        }
     
        /**
         * 查询操作:
         * 查询操作有两种可能:查询一张表或者查询某条数据
         *
         * 注意事项:
         * 在查询某条数据时要注意--因为此处是按照personid来查询
         * 某条数据,但是同时可能还有其他限制.例如:
         * 要求personid为2且name为xiaoming1
         * 所以在查询时分为两步:
         * 第一步:
         * 解析出personid放入where查询条件
         * 第二步:
         * 判断是否有其他限制(如name),若有则将其组拼到where查询条件.
         *
         * 详细代码见下.
         */
        @Override
        public Cursor query(Uri uri, String[] projection, String selection,String[] selectionArgs, String sortOrder) {
            SQLiteDatabase db = mSQLiteDatabaseOpenHelper.getWritableDatabase();
            Cursor cursor =null;
            switch (mUriMatcher.match(uri)) {
            // 查询表
            case PERSON_DIR:
                cursor = db.query(person, projection, selection, selectionArgs,null, null, sortOrder);
                break;
            // 按照id查询某条数据
            case PERSON:
                // 第一步:
                long id = ContentUris.parseId(uri);
                String where = personid= + id;
                // 第二步:
                if (selection != null && !.equals(selection.trim())) {
                    where = selection +  and  + where;
                }
                cursor = db.query(person, projection, where, selectionArgs, null, null, sortOrder);
                break;
            default:
                throw new IllegalArgumentException(unknown uri + uri.toString());
            }
            return cursor;
        }
         
     
    }


    SQLiteDatabaseOpenHelper如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    package cn.testcontentprovider;
    import android.content.Context;
    import android.database.sqlite.SQLiteDatabase;
    import android.database.sqlite.SQLiteOpenHelper;
    public class SQLiteDatabaseOpenHelper extends SQLiteOpenHelper {
        public SQLiteDatabaseOpenHelper(Context context) {
            super(context, contentprovidertest.db, null, 1);
        }
     
        @Override
        public void onCreate(SQLiteDatabase db) {
            db.execSQL(create table person(personid integer primary key autoincrement,name varchar(20),phone varchar(12),salary  Integer(12)));    
        }
     
        //当数据库版本号发生变化时调用该方法
        @Override
        public void onUpgrade(SQLiteDatabase db, int arg1, int arg2) {
            //db.execSQL(ALTER TABLE person ADD phone varchar(12) NULL);
            //db.execSQL(ALTER TABLE person ADD salary  Integer NULL);
        }
     
    }


    MainActivity如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    package cn.testcontentprovider;
    import android.app.Activity;
    import android.os.Bundle;
    public class MainActivity extends Activity {
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
        }
     
    }


    AndroidManifest.xml如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    <!--?xml version=1.0 encoding=utf-8?-->
    <manifest android:versioncode="1" android:versionname="1.0" package="cn.testcontentprovider" xmlns:android="http://schemas.android.com/apk/res/android">
     
        <uses-sdk android:minsdkversion="8" android:targetsdkversion="8">
     
        <uses-permission android:name="android.permission.INTERNET">
        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE">
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE">
        <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS">
         
         
             
                <intent-filter>
                     
     
                    <category android:name="android.intent.category.LAUNCHER">
                </category></action></intent-filter>
            </activity>
             
             <provider android:authorities="cn.bs.testcontentprovider" android:exported="true" android:name="cn.testcontentprovider.ContentProviderTest">
        </provider></application>
     
    </uses-permission></uses-permission></uses-permission></uses-permission></uses-sdk></manifest>


    main.xml如下:

    1
    <relativelayout android:layout_height="match_parent" android:layout_width="match_parent" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"><button android:layout_centerinparent="true" android:layout_height="wrap_content" android:layout_width="wrap_content" android:text="该应用包含一个自定义的ContentProvider" android:textsize="15sp"></button></relativelayout>



    以下代码为工程TestBaidu

    MainActivity如下:

    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
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    package cn.testbaidu;
    import android.net.Uri;
    import android.os.Bundle;
    import android.os.Handler;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.app.Activity;
    import android.content.ContentResolver;
    import android.content.ContentValues;
    import android.database.ContentObserver;
    import android.database.Cursor;
    /**
     * Demo描述:
     * 应用A(TestBaidu)调用另外一个应用(TestContentProvider)中的自定义ContentProvider,即:
     * 1 自定义ContentProvider的使用
     * 2 其它应用调用该ContentProvider
     * 3 ContentObserver的使用
     *
     * 备注说明:
     * 1 该例子在以前版本的基础上整理了代码
     * 2 该例子在以前版本的基础上融合了ContentObserver的使用
     *   利用ContentObserver随时监听ContentProvider的数据变化.
     *   为实现该功能需要在自定义的ContentProvider的insert(),update(),delete()
     *   方法中调用getContext().getContentResolver().notifyChange(uri, null);
     *   向外界通知该ContentProvider里的数据发生了变化 ,以便ContentObserver作出相应 
     *
     * 测试方法:
     * 1 依次测试ContentProvider的增查删改(注意该顺序)!!
     * 2 其它应用查询该ContentProvider的数据
     *
     */
    public class MainActivity extends Activity {
        private Button mAddButton;
        private Button mDeleteButton;
        private Button mUpdateButton;
        private Button mQueryButton;
        private Button mTypeButton;
        private long lastTime=0;
        private ContentResolver mContentResolver;
        private ContentObserverSubClass mContentObserverSubClass;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            init();
            initContentObserver();
        }
     
        private void init() {
            mContentResolver=this.getContentResolver();
             
            mAddButton=(Button) findViewById(R.id.addButton);
            mAddButton.setOnClickListener(new ClickListenerImpl());
             
            mDeleteButton=(Button) findViewById(R.id.deleteButton);
            mDeleteButton.setOnClickListener(new ClickListenerImpl());
             
            mUpdateButton=(Button) findViewById(R.id.updateButton);
            mUpdateButton.setOnClickListener(new ClickListenerImpl());
             
            mQueryButton=(Button) findViewById(R.id.queryButton);
            mQueryButton.setOnClickListener(new ClickListenerImpl());
             
            mTypeButton=(Button) findViewById(R.id.typeButton);
            mTypeButton.setOnClickListener(new ClickListenerImpl());
             
        }
         
         
     
        // 注册一个针对ContentProvider的ContentObserver用来观察内容提供者的数据变化
        private void initContentObserver() {
            Uri uri = Uri.parse(content://cn.bs.testcontentprovider/person);
            mContentObserverSubClass=new ContentObserverSubClass(new Handler());
            this.getContentResolver().registerContentObserver(uri, true,mContentObserverSubClass);
        }
         
        @Override
        protected void onDestroy() {
            super.onDestroy();
            if (mContentObserverSubClass!=null) {
                this.getContentResolver().unregisterContentObserver(mContentObserverSubClass);
            }
        }
     
         
         
         
        // 自定义一个内容观察者ContentObserver
        private class ContentObserverSubClass extends ContentObserver {
     
            public ContentObserverSubClass(Handler handler) {
                super(handler);
            }
     
            //采用时间戳避免多次调用onChange( )
            @Override
            public void onChange(boolean selfChange) {
                super.onChange(selfChange);
                System.out.println(ContentObserver onChange() selfChange=+ selfChange);
                if (System.currentTimeMillis()-lastTime>2000) {
                    ContentResolver resolver = getContentResolver();
                    Uri uri = Uri.parse(content://cn.bs.testcontentprovider/person);
                    // 获取最新的一条数据
                    Cursor cursor = resolver.query(uri, null, null, null,personid desc limit 1);
                    while (cursor.moveToNext()) {
                        int personid = cursor.getInt(cursor.getColumnIndex(personid));
                        System.out.println(内容提供者中的数据发生变化,现数据中第一条数据的personid=+ personid);
                    }
                    cursor.close();
                    lastTime=System.currentTimeMillis();
                }else{
                    System.out.println(时间间隔过短,忽略此次更新);
                }
                 
                 
            }
             
            @Override
            public boolean deliverSelfNotifications() {
                return true;
            }
             
        }
         
         
         
         
     
        private class ClickListenerImpl implements OnClickListener {
            @Override
            public void onClick(View v) {
                switch (v.getId()) {
                case R.id.addButton:
                    Person person = null;
                    for (int i = 0; i < 5; i++) {
                        person = new Person(xiaoming + i, 9527 + i, (8888 + i));
                        testInsert(person);
                    }
                    break;
                case R.id.deleteButton:
                    testDelete(1);
                    break;
                case R.id.updateButton:
                    testUpdate(3);
                    break;
                case R.id.queryButton:
                    // 查询表
                    // queryFromContentProvider(-1);
     
                    // 查询personid=2的数据
                    testQuery(2);
                    break;
                case R.id.typeButton:
                    testType();
                    break;
                default:
                    break;
                }
     
            }
     
        }
        private void testInsert(Person person) {
            ContentValues contentValues=new ContentValues();
            contentValues.put(name, person.getName());
            contentValues.put(phone, person.getPhone());
            contentValues.put(salary,person.getSalary());
            Uri insertUri=Uri.parse(content://cn.bs.testcontentprovider/person);
            Uri returnUri=mContentResolver.insert(insertUri, contentValues);
            System.out.println(新增数据:returnUri=+returnUri);
        }
         
        private void testDelete(int index){
            Uri uri=Uri.parse(content://cn.bs.testcontentprovider/person/+String.valueOf(index));
            mContentResolver.delete(uri, null, null);
        }
         
        private void testUpdate(int index){
            Uri uri=Uri.parse(content://cn.bs.testcontentprovider/person/+String.valueOf(index));
            ContentValues values=new ContentValues();
            values.put(name, hanmeimei);
            values.put(phone, 1234);
            values.put(salary, 333);
            mContentResolver.update(uri, values, null, null);
        }
     
        private void testQuery(int index) {
            Uri uri=null;
            if (index<=0) {
                //查询表
                uri=Uri.parse(content://cn.bs.testcontentprovider/person);
            } else {
                 //按照id查询某条数据
                uri=Uri.parse(content://cn.bs.testcontentprovider/person/+String.valueOf(index));
            }
             
            //对应上面的:查询表
            //Cursor cursor= mContentResolver.query(uri, null, null, null, null);
             
            //对应上面的:查询personid=2的数据
            //注意:因为name是varchar字段的,所以应该写作name='xiaoming1'
            //     若写成name=xiaoming1查询时会报错
            Cursor cursor= mContentResolver.query(uri, null, name='xiaoming1', null, null);
             
            while(cursor.moveToNext()){
                int personid=cursor.getInt(cursor.getColumnIndex(personid));
                String name=cursor.getString(cursor.getColumnIndex(name));
                String phone=cursor.getString(cursor.getColumnIndex(phone));
                int salary=cursor.getInt(cursor.getColumnIndex(salary));
                System.out.println(查询得到:personid= + personid+,name=+name+,phone=+phone+,salary=+salary);
            }
            cursor.close();
        }
         
        private void testType(){
            Uri dirUri=Uri.parse(content://cn.bs.testcontentprovider/person);
            String dirType=mContentResolver.getType(dirUri);
            System.out.println(dirType:+dirType);
             
            Uri itemUri=Uri.parse(content://cn.bs.testcontentprovider/person/3);
            String itemType=mContentResolver.getType(itemUri);
            System.out.println(itemType:+itemType);
        }
     
    }



    Person如下:

    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
    44
    45
    46
    47
    48
    49
    50
    package cn.testbaidu;
     
    public class Person {
        private Integer id;
        private String name;
        private String phone;
        private Integer salary;
        public Person(String name, String phone,Integer salary) {
            this.name = name;
            this.phone = phone;
            this.salary=salary;
        }
        public Person(Integer id, String name, String phone,Integer salary) {
            this.id = id;
            this.name = name;
            this.phone = phone;
            this.salary=salary;
        }
        public Integer getId() {
            return id;
        }
        public void setId(Integer id) {
            this.id = id;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public String getPhone() {
            return phone;
        }
        public void setPhone(String phone) {
            this.phone = phone;
        }
        public Integer getSalary() {
            return salary;
        }
        public void setSalary(Integer salary) {
            this.salary = salary;
        }
        @Override
        public String toString() {
            return Person [id= + id + , name= + name + , phone= + phone+ , salary= + salary + ];
        }
         
         
         
    }
  • 相关阅读:
    随机图片
    单页网站
    最安全的聊天工具——Cryptocat
    一个游戏——小黑屋
    SAO Utils – SAO风格启动菜单
    对话框实现
    抖动文字
    Leetcode: 22. Generate Parentheses
    Leetcode: 21. Merge Two Sorted Lists
    Leetcode: 20. Valid Parentheses
  • 原文地址:https://www.cnblogs.com/xiaoxiaoshen/p/5191186.html
Copyright © 2020-2023  润新知