android 四大组件之ContentProvider

  ContentProvider是android四大组件之一,从名字可以看出,就是内容提供者,让其他app可以访问到该应用暴露的数据,实际上也是如此,一般情况下,不会用到ContentProvider,但是获取联系人,也就间接的使用到了,下面简单介绍下ContentProvider的使用

1.创建一个ContentProvider的实现类:

  新建一个类并继承ContentProvider的类,四大组件都是如此做的,ContentProvider是一个抽象类, 有六个抽象方法 onCreate、getType、delete、update、insert和query,并从写这六个方法

这里写图片描述

  看到delete、update、insert和query这些方法,刚好对应着数据的增删改查四个方法,这些用于供外部应用往ContentProvider增删改查数据,其实的确如此。onCreate方法,该方法在ContentProvider创建后就会被调用,Android开机后,ContentProvider在其它应用第一次访问它时才会被创建,getType方法,该方法用于返回当前Url所代表数据的MIME类型

getType方法
  1)如果操作的数据属于集合类型,那么MIME类型字符串应该以vnd.android.cursor.dir/开头,

  例如:要得到所有person记录的Uri为content://com.app.wurui.providerdemo.myprovider/person,那么返回的MIME类型字符串应该为:”vnd.android.cursor.dir/person”。

  2)如果要操作的数据属于非集合类型数据,那么MIME类型字符串应该以vnd.android.cursor.item/开头,

  例如:得到id为10的person记录,Uri为content://com.app.wurui.providerdemo.myprovider/person/10,那么返回的MIME类型字符串为:”vnd.android.cursor.item/person”

2.注册

  也是在<\application>节点下进行注册

这里写图片描述

3.外部访问地址

  1)、每一个ContentProvider都拥有一个公共的URI,这个URI用于表示这个ContentProvider所提供的数据

  2)、Android所提供的ContentProvider都存放在android.provider包中。 将其分为A,B,C,D 4个部分,也可以使用三部分,去掉D部分:

这里写图片描述

  A:标准前缀,用来说明一个Content Provider控制这些数据,无法改变的;”content://”

  B:URI 的标识,用于唯一标识这个ContentProvider,外部调用者可以根据这个标识来找到它。它定义了是哪个Content Provider提供这些数据。对于第三方应用程序,为了保证URI标识的唯一性,它必须是一个完整的、小写的类名。这个标识在 元素的 authorities属性中说明:一般是定义该ContentProvider的包.类的名称
  
  C:路径(path),通俗的讲就是你要操作的数据库中表的名字,或者你也可以自己定义,记得在使用的时候保持一致就可以了; “content://com.app.wurui.providerdemo.myprovider/person/1”
  
  D:如果URI中包含表示需要获取的记录的ID;则就返回该id对应的数据,如果没有ID,就表示返回全部; “content://com.app.wurui.providerdemo.myprovider/person/tablename/#” #表示数据id

4.UriMatcher类和ContentUris类介绍

  在应用ContentProvider之前,先了解俩个类,是android系统专门为ContentProvider提供解析Uri的工具类

1).UriMatcher类
   该类提供了两个方法,addURI 和match方法,主要用于匹配Uri

这里写图片描述

2).ContentUris类
   该类提供了三个静态方法,withAppendedId、parseId和appendId方法

这里写图片描述

   上面几个方法,注释写的很清楚,在此不在解释了

5.ContentProvider的简单实例 这里用数据库来存储数据

  此处不介绍数据库

public class DBHelper extends SQLiteOpenHelper {
    public DBHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
    }

    public DBHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version, DatabaseErrorHandler errorHandler) {
        super(context, name, factory, version, errorHandler);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("create table person(_id integer primary key autoincrement, name varchar)");
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }
}
public class MyProvider extends ContentProvider {
    private DBHelper mDBHelper;
    private static UriMatcher mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);

    static {
        mUriMatcher.addURI("com.app.wurui.providerdemo.myprovider", "person", 1);
        mUriMatcher.addURI("com.app.wurui.providerdemo.myprovider", "person/#", 2);
    }

    @Override
    public boolean onCreate() {
        mDBHelper = new DBHelper(getContext(), "wurui.db", null, 1);
        return false;
    }

    @Nullable
    @Override//此方法如果正常返回不能关闭数据库连接,projection查询的条目, selection 条件 selectionArgs 条件的参数 sortOrder 排序
    public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
        SQLiteDatabase database = mDBHelper.getReadableDatabase();
        long code = mUriMatcher.match(uri);
        Cursor cursor = null;
        if(code == 1){
            cursor = database.query("person", projection, selection, selectionArgs, null, null, sortOrder);
        } else if(code == 2){
            long id = ContentUris.parseId(uri);
            cursor = database.query("person", null, new String("_id = ?"), new String[]{String.valueOf(id)}, null, null, null);
        } else {
            database.close();
            new RuntimeException("Uri不合法");
        }
        return cursor;
    }

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

    @Nullable
    @Override //values 添加的数据 返回的是添加进去的Uri
    public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
        SQLiteDatabase database = mDBHelper.getReadableDatabase();
        long code = mUriMatcher.match(uri);
        Uri result = null;
        if(code == 1){
            long id = database.insert("person", null, values);
            result = ContentUris.withAppendedId(uri, id);
        } else {
            database.close();
            new RuntimeException("Uri不合法");
        }
        database.close();
        return result;
    }

    @Override//返回值是删除了多少条数据
    public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
        SQLiteDatabase database = mDBHelper.getReadableDatabase();
        long code = mUriMatcher.match(uri);
        int deleteCount = 0;
        if(code == 1){
            deleteCount = database.delete("person", selection, selectionArgs);
        } else if(code == 2){
            long id = ContentUris.parseId(uri);
            deleteCount = database.delete("person", "_id = ?", new String[]{String.valueOf(id)});
        } else {
            database.close();
            new RuntimeException("Uri不合法");
        }
        database.close();
        return deleteCount;
    }

    @Override//返回值是更新了多少条数据
    public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {
        SQLiteDatabase database = mDBHelper.getReadableDatabase();
        long code = mUriMatcher.match(uri);
        int updateCount = 0;
        if(code == 1){
            updateCount = database.update("person", values, selection, selectionArgs);
        } else if(code == 2){
            long id = ContentUris.parseId(uri);
            updateCount = database.update("person", values, "_id = ?", new String[]{String.valueOf(id)});
        } else {
            database.close();
            new RuntimeException("Uri不合法");
        }
        database.close();
        return updateCount;
    }
}

  ContentProvider就写好了,为了验证是否正确,在另一个app调用

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/insert"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="insert"/>

    <Button
        android:id="@+id/query"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="query"/>

    <Button
        android:id="@+id/update"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="update"/>

    <Button
        android:id="@+id/delete"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="delete"/>

</LinearLayout>
public class MainActivity extends AppCompatActivity {
    private int i = 0;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        MyOnClickListener listener = new MyOnClickListener();
        findViewById(R.id.insert).setOnClickListener(listener);
        findViewById(R.id.delete).setOnClickListener(listener);
        findViewById(R.id.query).setOnClickListener(listener);
        findViewById(R.id.update).setOnClickListener(listener);
    }

    class MyOnClickListener implements View.OnClickListener{

        @Override
        public void onClick(View v) {
            switch (v.getId()){
                case R.id.insert:
                    insert();
                    break;
                case R.id.delete:
                    delete();
                    break;
                case R.id.update:
                    upData();
                    break;
                case R.id.query:
                    query();
                    break;
            }
        }
    }

    private void upData() {
        ContentResolver resolver = getContentResolver();
        ContentValues values = new ContentValues();
        values.put("name", "345");
        int count = resolver.update(Uri.parse("content://com.app.wurui.providerdemo.myprovider/person"), values, null,  null);
        System.out.println("更新了" + count + "条----------------------------------------");
    }

    private void delete() {
        ContentResolver resolver = getContentResolver();
        int count = resolver.delete(Uri.parse("content://com.app.wurui.providerdemo.myprovider/person"), "_id = ?", new String[]{String.valueOf(i)});
        System.out.println("删除了" + count + "条----------------------------------------");
        --i;
    }

    private void insert() {
        ContentResolver resolver = getContentResolver();
        ContentValues valus = new ContentValues();
        valus.put("name", "wurui" + i);
        Uri uri = resolver.insert(Uri.parse("content://com.app.wurui.providerdemo.myprovider/person"), valus);
        ++i;
        Cursor cursor = resolver.query(uri, null, null, null, null);
        if(cursor != null){
            if(cursor.moveToNext()){
                String name = cursor.getString(cursor.getColumnIndex("name"));
                int id = cursor.getInt(cursor.getColumnIndex("_id"));
                System.out.println("新增的数据   _id = " + id + " name = " + name + "----------------------------------------");
            }
        }
    }

    private void query() {
        ContentResolver resolver = getContentResolver();
        Uri uri = Uri.parse("content://com.app.wurui.providerdemo.myprovider/person");
        Cursor cursor = resolver.query(uri, null, null, null, null);
        if(cursor != null){
            while (cursor.moveToNext()){
                int id = cursor.getInt(0);
                String name = cursor.getString(1);
                System.out.println("id = " + id + " name = " + name);
            }
            cursor.close();
        }
    }
}

   以上就简单实现了ContentProvider的实例

6.监听ContentProvider中数据的变化

  1.继承ContentObserver类,并重写onChange方法

public class MyObserver extends ContentObserver {
    /**
     * Creates a content observer.
     *
     * @param handler The handler to run {@link #onChange} on, or null if none.
     */
    public MyObserver(Handler handler) {
        super(handler);
    }

    @Override
    public void onChange(boolean selfChange) {
        super.onChange(selfChange);
        System.out.println("改变了");
    }

}

  2.1注册对指定Uri的监听函数,一旦该Uri指向的内容发生改变,将通知到MyObserver类的onChange方法

getContentResolver().registerContentObserver(Uri.parse("content://com.app.wurui.providerdemo.myprovider/person"), true, mMyObserver);

  2.2当程序退出或者不需要再监听Uri的变化时,要主动取消对Uri的监听

        if(mMyObserver != null){
            getContentResolver().unregisterContentObserver(mMyObserver);
            mMyObserver = null;
        }

  3.在ContentProvider里,每当特定Uri上的数据发生变化,要触发对调用者对通知。通知使用ContentResolver的notifyChange()方法触发。比如删除数据时:

    @Override//返回值是删除了多少条数据
    public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
        SQLiteDatabase database = mDBHelper.getReadableDatabase();
        long code = mUriMatcher.match(uri);
        int deleteCount = 0;
        if(code == 1){
            deleteCount = database.delete("person", selection, selectionArgs);
        } else if(code == 2){
            long id = ContentUris.parseId(uri);
            deleteCount = database.delete("person", "_id = ?", new String[]{String.valueOf(id)});
        } else {
            database.close();
            new RuntimeException("Uri不合法");
        }
        //当删除数据成功时,就会触发
        getContext().getContentResolver().notifyChange(uri, null);
        database.close();
        return deleteCount;
    }

这里写图片描述

  ContentProvider就讲到这里,相信大家对ContentProvider非常熟悉了、、、、、、、

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值