ContentProvider,ContentResolver和ContentObserver 使用

1 ContentProvider内容提供者

四大组件之一,实现不同程序实现数据的共享。联系人应用就使用了ContentProvider,比如你在自己的应用可以读取和修改联系人的数据(获得相应权限)。
其实它也是一个中间人,真正的数据源是文件或者SQLite。通过Uri向外暴露访问地址 

2 ContentResolver内容解析者

一个应用通过ContentResolver可以访问另一个应用通过ContentProvider提供的数据(当然也可以在自己的应用中)。

3 ContentObserver内容观察者

监听数据库的变化,执行相应的操作。更新UI
mContentResolver.registerContentObserver(WicketProvider.CONTENT_URI, true, mChatObserver);

使用案例:

1 自定义StatusProvider
   a 自定义数据库工具类
   b 自定义StatusProvider继承ContentProvider 覆写对应的方法
      创建,增删改查方法
package com.ecarx.systemui.plugin.statusbar.provider;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.net.Uri;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

public class StatusProvider extends ContentProvider {

    // 声明当前ContentProvider组件的唯一标识(Authority),注:必须使用小写字母
    private static final String STATUSPROVIDER_AUTHORITY = "com.ecarx.systemui.plugin.statusbar.provider";
    private String exitApp = "";

    @Override
    public boolean onCreate() {
        return true;
    }

    @Nullable
    @Override
    public Cursor query(@NonNull Uri uri, @Nullable String[] strings, @Nullable String s, @Nullable String[] strings1, @Nullable String s1) {
        MatrixCursor cursor = new MatrixCursor(strings);
        cursor.addRow(new Object[]{exitApp});
        return cursor;
    }

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

    @Nullable
    @Override
    public Uri insert(@NonNull Uri uri, @Nullable ContentValues contentValues) {
        exitApp = contentValues.getAsString("exitApp");
        //need notifyChange 
        getContext().getContentResolver().notifyChange(uri, null);
        return uri;
    }

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

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

c 清单文件中配置provider

<provider
    android:authorities="com.ecarx.systemui.plugin.statusbar.provider"
android:name=".statusbar.provider.StatusProvider"
android:enabled="true"
android:exported="true"/>

2 通过ContentResolver更新数据(ContentProvider所在进程或其他进程均可),触发ContentProvider提供的对应方法

private String statusbarProvider = "com.ecarx.systemui.plugin.statusbar.provider";
    private Uri uri = Uri.parse("content://"+statusbarProvider);
    public void exitApp(String exitApp) {
        if("launcher".contains(exitApp) || "com.ecarx.systemui.plugin".contains(exitApp)){
            return;
        }
        ContentValues values = new ContentValues();
        values.put("exitApp",exitApp);
        Uri uriResult = mContentResolver.insert(uri,values);
    }

3 其他应用进程注册ContentObserver监听数据变化,更新UI

private Uri uri = Uri.parse("content://com.ecarx.systemui.plugin.statusbar.provider");

    private void registerObeserver() {
        Log.e(TAG, "registerObeserver");
        getContentResolver().registerContentObserver(uri, true, observer);
    }

    ContentObserver observer = new ContentObserver(new Handler(Looper.getMainLooper())) {
        @Override
        public void onChange(boolean selfChange) {
            super.onChange(selfChange);
            Log.e(TAG, "observer - onChange");
            Cursor cursor = getContentResolver().query(uri, new String[]{"exitApp"}, null, null, null);
            while (cursor.moveToNext()) {
                String result = cursor.getString(0);
                Log.e(TAG, "observer - result : " + result);
            }
        }
    };

ContentResolver查询方法

 1 public class MainActivity extends Activity{
 2          private TextView tv_info;
 3          private ContentResolver resolver;
 4          private Uri uri = Uri.parse("content://com.user.contentprovider.users/users");
 5       @Override
 6       protected void onCreate(Bundle savedInstanceState) {
 7           // TODO Auto-generated method stub
 8            super.onCreate(savedInstanceState);
 9            setContentView(R.layout.layout_main);
10             tv_info = (TextView)findViewById(R.id.tv_info);
11            resolver = getContentResolver();
12       }
13         public void click(View v){
14              switch (v.getId()) {
15              case R.id.bt_query:
16               //建表时的语句:create table t_user(_id integer primary key,uname,upass,money)
17               query();//调用自定义的查询所有数据的方法
18               break;
19             case R.id.bt_insert:
20               insert();//调用自定义的插入数据的方法
21               break;
22             case R.id.bt_update:
23             //请自行实现
24              break;
25           default:
26             break;
27         }
28      }
29      private void insert() {
30        //调用自定义的插入数据的方法(硬编码)
31         ContentValues values = new ContentValues();
32           values.put("uname", "zhang");
33         values.put("upass", "321");
34           values.put("money", "99");
35         Uri nUri = resolver.insert(uri, values);//sqlite会自动指定主键id
36        long newId = ContentUris.parseId(nUri);//获取新插入的id
37       Toast.makeText(this, ""+newId, 0).show();
38    }
39    private void query() {
40     //自定义的查询所有数据的方法
41      Cursor c = resolver.query(uri , new String[]{"_id","uname","upass","money"}, null, null,null);
42     String text = "";
43     while(c.moveToNext()){
44           text +=c.getString(0)+","+c.getString(1)+","+c.getString(2)+","+c.getString(3)+"\n";
45     }
46      tv_info.setText(text);
47    }
48 }
【备注:】
ContentProvider是单例模式的,当多个应用程序通过使用ContentResolver 来操作使用ContentProvider 提供的数据时,ContentResolver 调用的数据操作会委托给同一个ContentProvider 来处理。这样就能保证数据的一致性。
Cursor 游标,查询时返回的结果集 
具体应用参考实际开发项目。
 
使用ContentProvider和ContentResolver时,是否可用第三方ORM数据库工具,如GreenDao操作数据库?
不建议使用。这两者是通过Uri来操作数据,而GreenDao是通过bean来操作数据库。
 
SQLiteDatabase 和 ContentResolver操作数据库api有所不同,前者操作对象为表,后者为Uri。
 
posted @ 2018-05-11 16:20  随易来了  阅读(462)  评论(0编辑  收藏  举报