zoukankan      html  css  js  c++  java
  • ContentProvider和ContentResolver的使用

    ContentProvider

    ContentProvider 在android中的作用是对外共享数据,也就是说你可以通过ContentProvider把应用中的数据共享给其他应用访问,其他应用可以通过ContentProvider 对你应用中的数据进行添删改查。
    ContentProvider的就是自定义增删改查接口并暴露出去,让别的应用访问自己的数据。ContentResolver就是按照一定规则访问内容提供者的数据。

    ContentProvider对外共享数据步骤:

    步骤

    1. 定义一个类 继承 ContentProvider
    2. 定义匹配规则 uri
    3. 通过静态代码块添加匹配规则 
    4.在manifest.xml中配置contentProvider.  

    Uri介绍

    uri代表了要操作的数据

    上面我们提到了Android提供内容的叫Provider,那么在Android中怎么区分各个Provider?

    Uri作为唯一的标识来标识这个Provider。

    ContentProvider的scheme为:content://
    Authority 用于唯一标识这个ContentProvider,外部调用者可以根据这个标识来找到它。
    路径(path)可以用来表示我们要操作的数据,路径的构建应根据业务而定,如下:
    要操作file表中id为10的记录,可以构建这样的路径:/file/10
    要操作file表中id为10的记录的name字段, file/10/name
    要操作file表中的所有记录,可以构建这样的路径:/file

    当然要操作的数据可以是数据库,也可以是文件、xml或网络等其他存储方式。

    代码示例

    public class FileProvider  extends ContentProvider {
    
        private Context mContext;
        private static final int QUEYSUCESS = 0;
        private static final int INSERTSUCESS = 1;
        //UriMatcher.NO_MATCH表示不匹配任何路径的返回码
        private static UriMatcher mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
    
        private SQLiteDatabase mDb;
        private String mTableName = DbOpenHelper.STUDENT_TABLE_NAME;
        static{
            //注册所有要匹配的uri
            mUriMatcher.addURI("com.itcast.contentp.FileProvider", "query", QUEYSUCESS);
            mUriMatcher.addURI("com.itcast.contentp.FileProvider", "insert", INSERTSUCESS);
        }
    
        //该方法在其它应用第一次访问它时才会被创建
        @Override
        public boolean onCreate() {        
            mContext = getContext();
            mDb = new DbOpenHelper(mContext).getWritableDatabase();
            return false;
        }
    
        /**
        *public final Cursor query (Uri uri, String[] projection,String selection,String[] selectionArgs, String sortOrder)
        *projection : 这个参数告诉查询要返回的列(Column)即需要的字段,比如Contacts Provider提供了联系人的ID和联系人的NAME等内容.
        *selection :查询where字句
        *selectionArgs : 查询条件属性值
        *sortOrder :结果排序
        */
        @Override
        public Cursor query(Uri uri, String[] arg1, String arg2, String[] arg3,String arg4) {
            if (mUriMatcher.match(uri)== QUEYSUCESS ) {//uri匹配后进行下面的操作
                Cursor cursor = mDb.query(tableName, arg1, arg2, arg3, null, null, null);
                getContext().getContentResolver().notifyChange(uri, null);
                return cursor;
            }else{
                throw new IllegalArgumentException("match fail");
            }
    }
    这里只给出部分代码。。。。。。


    ContentResolver

    使用ContentResolver调用ContentProvider提供的接口,对ContentProvider中的数据进行添加、删除、修改和查询操作时。

    可以使用Activity提供的getContentResolver()方法来获取ContentResolver对象。 ContentResolver 类提供了与ContentProvider类相同签名的四个方法:

    • public Uri insert(Uri uri, ContentValues values)
    • public int delete(Uri uri, String selection, String[] selectionArgs)。
    • public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs)
    • public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)


    1.对ContentProvider中的数据进行增删改查

    直接看代码:

    //uriQuery必须与要查询的ContentProvider中的要操作数据的uri保持一致(btw 这里只给了查询好插入的例子)

    ContentValues values = new ContentValues();
    Cursor cursor = getContentResolver().query(uriQuery, null, null, null, null);
    int count = cursor.getCount(); //获取到一共有多少行
    int contact_id = count + 1;
    
    ContentValues nameValues = new ContentValues();
    nameValues.put("name", name);
    nameValues.put("mime_type", "vnd.android.cursor.item/name");
    nameValues.put("contact_id", contact_id);
    getContentResolver().insert(uriInsert, nameValues);

    2.监听ContentProvider中数据的变化

    在ContentProvider 发生数据变化时调用getContentResolver().notifyChange(uri, null)来通知注册在此URI上的访问者。

    当数据放生变化时会调用ContentObserver的onChange()来进行一系列的后续操作~~~

    如下: 

    public class MainActivity extends Activity {
    
        private Uri uri;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
    
            //注册
            uri = Uri.parse("content://com.example.contentp.AccountProvider"); 
            getContentResolver().registerContentObserver(uri, true, new MyObserver(new Handler())) 
    }
    }

    //监听到变化后调用onChange()来执行一系列操作

    private class MyObserver extends ContentObserver {
        Uri uri = Uri.parse("content://com.example.contentp.AccountProvider"); 

    public MyObserver(Handler handler) {

    super(handler);
    }
    @Override
    public void onChange(boolean selfChange) {
    Cursor cursor = getContentResolver().query(uri, new String[]{"file","mime_type","date"}, null, null, null);
    while(cursor.moveToNext()){
    //执行一些操作
    }
    }
    }

    ContentProviderClient 

    与ContentResolver一样都是用来对ContentProvider中的数据进行添加、删除、修改和查询操作的

    通过调用 getContentResolver().acquireContentProviderClient(authority) 方法获取 ContentProviderClient对象。

    用法跟ContentResolver相似,不同点是ContentProviderClient 对象必须在结束使用后,调用ContentProviderClient.release()来释放。这会是系统释放对应的ContentProvider对象。

    对于相同ContentProvider 的多次调用,推荐使用ContentProviderClient。

  • 相关阅读:
    IOS Charles(代理服务器软件,可以用来拦截网络请求)
    Javascript中addEventListener和attachEvent的区别
    MVC中实现Area几种方法
    Entity Framework Code First 中使用 Fluent API 笔记。
    自定义JsonResult解决 序列化类型 System.Data.Entity.DynamicProxies 的对象时检测到循环引用
    序列化类型 System.Data.Entity.DynamicProxies 的对象时检测到循环引用
    An entity object cannot be referenced by multiple instances of IEntityChangeTracker 的解决方案
    Code First :使用Entity. Framework编程(8) ----转发 收藏
    Code First :使用Entity. Framework编程(6) ----转发 收藏
    Code First :使用Entity. Framework编程(5) ----转发 收藏
  • 原文地址:https://www.cnblogs.com/lilykeke/p/10329964.html
Copyright © 2011-2022 走看看