ContentProvider总结及Loader的使用

概述

ContentProvider(内容提供者)是Android中的四大组件之一。主要用于程序间数据的共享(IPC的一种).
它提供了一套完整的机制,允许一个程序访问另一个应用程序,并且保证数据的安全性.
我们知道在Android中常见的数据存储方式有sharedpreferences,文件和数据库等,但是数据的访问方式会因为存储方式的不同而不同.
而且这些数据只能在应用内使用,而ContentProvider允许在程序间实现数据的共享,并且提供好了统一了数据的访问方式.

ContentResolver

访问内容提供器中共享的数据,需要借助通过ContentResolver,其中context.getContentResolver()方法可以获取到ContentResolver实例,
ContentResolver提供了一系列方法来对数据进行CRUD操作.

URI

统一资源标识符,结构和HTTP形式的URL是一样的.
代表了要操作的数据,每一个ContentProvider都拥有一个公共的URI,不能重复

<prefix>://<authority>/<data_type>/<id>

其中,<prefix>的值永远为content,不可更改

<authority>唯一标识符,用来定位ContentProvider,一般为自定义Provider的全路径名,保证唯一

<data_type>/<id>代表资源路径,如/person/2代表person表中id为2的数据

MIME

用于指定某个扩展名的文件用一种应用程序来打开,如application/pdf,text/css等,Android中的MIME类型有两种
* 多条记录
vnd.android.cursor.dir/vnd.xxx
* 单条记录
vnd.android.cursor.item/vnd.xxx

其中包含类型和子类型,/前面的类型是Android定义好的,不可更改,子类型中vnd.后面的可以随意指定.在使用Intent时,会用到MIME这玩意,根据Mimetype打开符合条件的活动。

自定义Contentprovider

  • 继承ContentProvider,并重写其中的一些方法,

其中OnCreate()方法在Provider初始化的时候执行

getType(URI uri)用于返回某一URI对应的MIME类型,运行在Binder线程池中

还有其他一些操作CRUD操作,运行在Binder线程池中

  • UriMatcher

用于冠关联Provider中的自定义URI和URI_CODE,通过addURI()将相应的Path和Code联系起来,通过match(uri)得到相应的CODE.


//为外部程序准备好一个所有地址匹配集合
static{
      uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
      uriMatcher.addURI(PROVIDER_NAME, "students", STUDENTS);
      uriMatcher.addURI(PROVIDER_NAME, "students/#", STUDENT_ID);
   }

// 取得数据的类型,此方法会在系统进行URI的MIME过滤时被调用。
@Override
 public String getType(Uri uri) {
    switch (uriMatcher.match(uri)){
       /**
       * Get all student records 
       */
       case STUDENTS:
       return "vnd.android.cursor.dir/vnd.example.students";

       /** 
       * Get a particular student
       */
       case STUDENT_ID:
       return "vnd.android.cursor.item/vnd.example.students";

       default:
       throw new IllegalArgumentException("Unsupported URI: " + uri);
   }
}
  • ContentUris
    用于操作Uri路径后面的ID部分

其中withAppendedId(uri, id)用于为路径加上ID部分:

Uri uri = Uri.parse("content://com.example.provider.College/students")  
Uri resultUri = ContentUris.withAppendedId(uri, 10);   
//生成后的Uri为:content://com.example.provider.College/students/10  

parseId(uri)方法用于从路径中获取ID部分:

Uri uri = Uri.parse("content://com.example.provider.College/students/10 ")  
long personid = ContentUris.parseId(uri);//获取的结果为:10 
  • 配置清单文件
<provider
        android:authorities="com.bobomee.android.contentproviderdemo"
        android:name=".BookContentProvider"/>

监听ContentProvider变化

如果ContentProvider的访问者需要知道ContentProvider中的数据发生变化,可以在ContentProvider发生数据变化时调用getContentResolver().notifyChange(uri, null)来通知注册在此URI上的访问者,

Uri insertUri = Uri.withAppendedPath(uri, "/" + rowId);
      Log.i(TAG, "insertUri:"+insertUri.toString());
      //发出数据变化通知(book表的数据发生变化)
      getContext().getContentResolver().notifyChange(uri, null);
      return insertUri;

Loader

Loader是3.0引入的API,可以优雅的实现异步,常用于Activity和Fragment中异步加载数据.防止引起内存泄漏,不仅如此,Loader还实时监听数据源,在配置发生改变后不会重新查询等.

Loader是一个抽象类,实际使用时,我们使用的是AsyncTaskLoader与CursorLoader,使用Loader,需要了解LoaderManager及LoaderCallbacks的API.关于Loader的详细介绍Android之Loader介绍

其中CursorLoader和Contentprovider一起使用再合适不过了

最后使用Contentprovider的小Demo:ProviderDemo

参考文章:

ContentProvider和Uri详解
Android - Content Providers
我是这样理解Android开发中的contentprovider的
Android开发教程:Android数据储存之ContentProvider
android ContentProvider使用详解
Android之Loader介绍
Android中Loader及LoaderManager的使用(附源码下载)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是在Android Studio中实现ContentProvider的步骤: 1. 创建一个新的Java类,命名为`DBHelper`,并继承自`SQLiteOpenHelper`类。在`DBHelper`类中,重写`onCreate()`和`onUpgrade()`方法,用于创建和升级数据库。 ```java public class DBHelper extends SQLiteOpenHelper { private static final String DATABASE_NAME = "mydatabase.db"; private static final int DATABASE_VERSION = 1; public DBHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } @Override public void onCreate(SQLiteDatabase db) { // 创建数据库表 db.execSQL("CREATE TABLE mytable (_id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT)"); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { // 升级数据库表 db.execSQL("DROP TABLE IF EXISTS mytable"); onCreate(db); } } ``` 2. 创建一个新的Java类,命名为`MyContentProvider`,并继承自`ContentProvider`类。在`MyContentProvider`类中,重写`onCreate()`、`query()`、`insert()`、`update()`和`delete()`方法,用于实现对数据的CRUD操作。 ```java public class MyContentProvider extends ContentProvider { private DBHelper dbHelper; @Override public boolean onCreate() { dbHelper = new DBHelper(getContext()); return true; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { SQLiteDatabase db = dbHelper.getReadableDatabase(); Cursor cursor = db.query("mytable", projection, selection, selectionArgs, null, null, sortOrder); cursor.setNotificationUri(getContext().getContentResolver(), uri); return cursor; } @Override public Uri insert(Uri uri, ContentValues values) { SQLiteDatabase db = dbHelper.getWritableDatabase(); long id = db.insert("mytable", null, values); getContext().getContentResolver().notifyChange(uri, null); return ContentUris.withAppendedId(uri, id); } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { SQLiteDatabase db = dbHelper.getWritableDatabase(); int count = db.update("mytable", values, selection, selectionArgs); getContext().getContentResolver().notifyChange(uri, null); return count; } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { SQLiteDatabase db = dbHelper.getWritableDatabase(); int count = db.delete("mytable", selection, selectionArgs); getContext().getContentResolver().notifyChange(uri, null); return count; } @Override public String getType(Uri uri) { return null; } } ``` 3. 在`AndroidManifest.xml`文件中注册`MyContentProvider`。 ```xml <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.myapp"> <application> <!-- ... --> <provider android:name=".MyContentProvider" android:authorities="com.example.myapp.provider" android:exported="true" /> </application> </manifest> ``` 4. 在需要访问`ContentProvider`的地方,使用`ContentResolver`类进行数据的访问。 ```java ContentResolver resolver = getContentResolver(); Cursor cursor = resolver.query(Uri.parse("content://com.example.myapp.provider/mytable"), null, null, null, null); // 处理查询结果 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值