美文网首页
Android 四大组件之一 ContentProvider

Android 四大组件之一 ContentProvider

作者: 戎码虫 | 来源:发表于2019-03-08 20:01 被阅读0次

简介

上一篇博客已经介绍了Android原生数据库的使用,本篇博客就来记录Android的四大组件之一的内容提供者(ContentProvider),ContentProvider主要用于不同应用之间实现数据共享的功能,Android系统也提供对应的接口供应用程序读取数据,比如多媒体、联系人、短信等,它的数据源不单单是数据库,还有可能是XML、文件、网络等;

数据共享

使用

在AndroidManifest注册

在Android文件AndroidManifest.xml注册
authorities:访问表的主机地址;
exported:是否允许对外应用程序访问,true允许,false不允许,默认false;

 <!--给内容提供者提供定义一个uri,一般建议使用包名+类名,以供其它程序调用 -->
<provider
    android:name="com.dream.contentprovider.provider.PersonProvider"
    android:authorities="com.dream.contentprovider"
    android:exported="true"/>
继承ContentProvider

Android系统为我们提供ContentProvider类,我们继承这个类实现onCreate()、getType()、insert()、delete()、update()、query();
onCreate():内容提供者初始化的时候调用,一般这里执行数据库创建、升级操作。
getType():根据给定的Uri返回一个MIME类型的数据。
insert():Uri表示需要操作哪张表,ContentValues需要插入的值,插入成功返回一个Uri;
delete():Uri表示需要操作哪张表,selection和selectionArgs表示筛选的条件,返回受影响的行。
update():Uri表示需要操作哪张表,ContentValues需要插入的值,selection和selectionArgs表示筛选的条件,返回受影响的行。
query():Uri表示需要操作哪张表,projection需要查询表中那些字段,selection和selectionArgs表示筛选的条件,sortOrder对查询查询结果进行排序,将查询结果放到Cursor返回。

public class PersonProvider extends ContentProvider {
    private static String TAG = PersonProvider.class.getSimpleName();

    //这里的AUTHORITY就是我们在AndroidManifest.xml中配置的authorities
    public static final String AUTHORITY = "com.dream.contentprovider";

    //常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码,也就是说如果找不到匹配的类型,返回-1
    private static final UriMatcher URI_MATCHER;

    //匹配不同的表的code
    private static final int ALL_PERSON = 1;
    private static final int PERSON = 2;

    //数据库的名字
    public static final String DB_NAME = "test.db";
    //数据库版本
    public static final int DB_VERSION = 1;
    //数据库表的名称
    private static final String TABLE_NAME = "person";

    private MyDBHelper dbHelper;
    private SQLiteDatabase db;

    static {
        //创建一个路径识别器
        URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
        //1.指定一个路径的匹配规则
        //如果路径满足content://com.dream.contentprovider.provider.PersonProvider/person,返回值就是(ALL_PERSON)=1
        URI_MATCHER.addURI(AUTHORITY, "/person", ALL_PERSON);
        //2.#号为通配符
        //如果路径满足content://com.dream.contentprovider.provider.PersonProvider/person/3,返回值就是(PERSON)=2
        URI_MATCHER.addURI(AUTHORITY, "/person/#", PERSON);
    }


    /**
     * 一般是对象第一次被创建时调用的方法
     *
     * @return
     */
    @Override
    public boolean onCreate() {
        dbHelper = new MyDBHelper(this.getContext(), DB_NAME, null, DB_VERSION);
        db = dbHelper.getReadableDatabase();
        return true;
    }


    /**
     * 让别人去调用返回结果
     *
     * @param uri           匹配条件
     * @param projection    选择的列
     * @param selection     查询条件
     * @param selectionArgs 查询条件的value
     * @param sortOrder     排序
     * @return
     */
    @Nullable
    @Override
    public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
        int type = URI_MATCHER.match(uri);
        switch (type) {
            case ALL_PERSON:
                return db.query(TABLE_NAME, projection, selection, selectionArgs, null, null, sortOrder);
            case PERSON:
                //获取具体某一行的数据
                String id = uri.getPathSegments().get(1);
                return db.query(TABLE_NAME, projection, "_id = ?", new String[]{id}, null, null, sortOrder);
            default:
                break;
        }
        return null;
    }

    //如果是单条记录应该返回以vnd.android.cursor.item/ 为首的字符串
    //如果是多条记录,应该返回vnd.android.cursor.dir/ 为首的字符串
    @Nullable
    @Override
    public String getType(@NonNull Uri uri) {
        int type = URI_MATCHER.match(uri);
        switch (type) {
            case ALL_PERSON:
                return "vnd.android.cursor.dir/vnd.com.dream.contentprovider.provider.person";
            case PERSON:
                return "vnd.android.cursor.item/vnd.com.dream.contentprovider.provider.person";
            default:
                return null;
        }
    }

    @Nullable
    @Override
    public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
        int type = URI_MATCHER.match(uri);
        switch (type) {
            case ALL_PERSON:
                long row = db.insert(TABLE_NAME, null, values);
                return ContentUris.withAppendedId(uri, row);
            case PERSON:
                long row2 = db.insert(TABLE_NAME, null, values);
                return ContentUris.withAppendedId(uri, row2);
            default:
                return null;
        }
    }

    @Override
    public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
        int type = URI_MATCHER.match(uri);
        int updateRow = 0;
        switch (type) {
            case ALL_PERSON:
                updateRow = db.delete(TABLE_NAME, selection, selectionArgs);
                break;
            case PERSON:
                //获取具体某一行的数据
                String id = uri.getPathSegments().get(1);
                updateRow = db.delete(TABLE_NAME, "_id = ?", new String[]{id});
                break;
            default:
                break;
        }
        return updateRow;
    }

    @Override
    public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {
        int type = URI_MATCHER.match(uri);
        int updateRow = 0;
        switch (type) {
            case ALL_PERSON:
                updateRow = db.update(TABLE_NAME, values, selection, selectionArgs);
                break;
            case PERSON:
                //获取具体某一行的数据
                String id = uri.getPathSegments().get(1);
                updateRow = db.update(TABLE_NAME, values, "_id = ?", new String[]{id});
                break;
            default:
                break;
        }
        return updateRow;
    }
}

当APP启动的时候,onCreate()方法被执行,此时已经创建了数据库。

跨进程调用

private static final Uri STUDENT_ALL_URI = Uri.parse("content://" + PersonProvider.AUTHORITY + "/person");拼接完整的地址为:"content://com.dream.contentprovider/person""content://com.dream.contentprovider/person/id",其中这个id表示表中数据的行数,id=0、1、 2 ...。当和UriMatcher 进行匹配返回匹配类型。不管是进程内还是跨进程之间通信关键是否URL正确,否则会出现如下错误:

URL有误
private static final Uri STUDENT_ALL_URI = Uri.parse("content://com.dream.contentprovider/person");
插入数据insert()
 mUserProvider = getContentResolver();
 ContentValues values = new ContentValues();
 values.put("name", "张三");
 values.put("age", "18");
 values.put("sex", "男");
 mUserProvider.insert(STUDENT_ALL_URI, values);
插入数据
插入数据delete()
 mUserProvider = getContentResolver();
 mUserProvider.delete(STUDENT_ALL_URI, "name = ?", new String[]{"张三"});
删除数据
更新数据update()
 mUserProvider = getContentResolver();
 ContentValues values = new ContentValues();
 values.put("age", "19");
 values.put("sex", "女");
 mUserProvider.update(STUDENT_ALL_URI, values, "name = ?", new String[]{"张三"});
更新数据
查询数据query()

记得关闭游标,防止内存泄漏

 mUserProvider = getContentResolver();
 String result = "";
 Cursor cursor = mUserProvider.query(STUDENT_ALL_URI, null, null, null);
 if (cursor != null) {
     try {
          while (cursor.moveToNext()) {
              String id = cursor.getString(cursor.getColumnIndex("_id"));
              String name = cursor.getString(cursor.getColumnIndex("NAME"));
              String age = cursor.getString(cursor.getColumnIndex("AGE"));
              String sex = cursor.getString(cursor.getColumnIndex("SEX"));
              result = result + "\n" + "_id=" + id + " name=" + name + " sex=" + sex + "  age=" + age;
          }
     } finally {
         cursor.close();
         cursor = null;
         mTextView.setText(result);
     }
 }
查询数据

相关文章

网友评论

      本文标题:Android 四大组件之一 ContentProvider

      本文链接:https://www.haomeiwen.com/subject/wirqoftx.html