android 四大组件之ContentProvider

来源:互联网 发布:苏有朋斥周杰炒作知乎 编辑:程序博客网 时间:2024/06/05 23:53

  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
原创粉丝点击