Android中ContentProvider简介

翻看Android源码可以发现,Android一般的代码架构如下:activity,service,receiver----contentProvider------db(file)

也就是说创建数据库保存数据,借助contentprovider对数据进行增删该查,上层利用Android组件进行交互。于是想着给自己新写的项目也添加个contentProvider来学习Android谷歌工程师的高大上,但从未用过contentprovider,这是第一次用,用完之后就发现一个问题

第一,contentprovider实际上就是将数据库的增删改查方法进行一个集成,给外界提供一个接口

第一,contentprovider是方便了应用程序之间(进程间)进行交换数据,如果你的apk的数据不需要与别的进程交换数据,根本无需使用contentprovider

第三,如果是一个程序间进行数据修改,完全可以自己集成一个提供增删改查的方法

所以呢,在你决定使用contentprovider之前先要看看你是否有使用它的必要。在解决问题之前,首先要分析问题,先动脑然后再动手

尽管如此,我还是依旧学习了一些contentprovider的用法,不为用在项目中,只是为了完善自己的知识体系。

既然明白contentProvider只是一个集成了增删改查的类给外界提供一个调用的接口,那么使用的思路,应该也很明确了

首先是创建数据库,自定义一个数据库的帮助类,来创建数据库

public class MyDataOpenHelper extends SQLiteOpenHelper {

    private String tableName;

    public MyDataOpenHelper(Context context, String name, int version) {
        super(context, name, null, version);
        tableName = name;
    }

    @Override
    public void onCreate(SQLiteDatabase db) {

        db.execSQL("CREATE TABLE " +
                tableName +
                " (" +
                "Id integer primary key autoincrement," +
                CustomProvider.COLUMN_AGE +
                "," +
                CustomProvider.COLUME_NAME+
                "," +
                CustomProvider.COLUME_ID +
                ")");

    }

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

    }
}

创建好数据库后创建一个自定义的provider

public class CustomProvider extends ContentProvider {

    private SQLiteOpenHelper mDataOpenHelper;
    private SQLiteDatabase mDB;
    private static final UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
    public static final String AUTHORITY = "customProvider";

    private static final int ALL_STUDENT = 0;
    private static final int STUDENT = 1;
    private static final int QUERY_BY_ID = 2;
    private static final int QUERY_BY_AGE = 3;
    private static final int QUERY_BY_NAME = 4;
    public static final String TABLE = "student";
    public static final String COLUMN_AGE = "age";
    public static final String COLUME_NAME = "name";
    public static final String COLUME_ID = "student_id";

    static {
        //第一个参数authority为域名:customProvider
        //第二个参数为路径:student/#
        //第三个参数为匹配成功后返回的code
       matcher.addURI(  AUTHORITY ,TABLE,ALL_STUDENT);
        matcher.addURI(AUTHORITY,TABLE + "/#",STUDENT);
    }


    @Override
    public boolean onCreate() {
        mDataOpenHelper = new MyDataOpenHelper(getContext(),TABLE,1);
        return false;
    }

    @Nullable
    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {

        mDB = mDataOpenHelper.getReadableDatabase();
        if (mDB.isOpen()){

            switch (matcher.match(uri)){
                case ALL_STUDENT:
                   return mDB.query(TABLE,projection,selection,selectionArgs,null,null,sortOrder);
                case STUDENT:
                    long id = ContentUris.parseId(uri);

                    return mDB.query(TABLE,null,"Id = " + id,selectionArgs,null,null,null);
                default:
                    break;
            }
            mDB.close();
        }
        return null;
    }

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

    @Nullable
    @Override
    public Uri insert(Uri uri, ContentValues values) {

        mDB = mDataOpenHelper.getWritableDatabase();
        if (mDB.isOpen()){

            long i = mDB.insert(TABLE,null,values);
            Log.i("fang","i = " + i);
            mDB.close();
        }
        return null;
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        return 0;
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
        return 0;
    }
}

在你创建时会提示你去继承5个方法,增删改查以及getType,在这里因为是为了熟悉provider的用法,所以只在增加和查询的方法中添加了一些代码

先分析一下,在这里定义了一个Urimatcher的实例,可以去匹配uri,在这里定义了三种情况

第一种:unknown

第二种:all_student:

第三种:student

自定义了之后去在Androidmanifest中去注册一下,需要声明authority域名属性,与类中的相同

<provider
            android:authorities="customProvider"
            android:name=".provider.CustomProvider"/>

也就是说如果程序想使用contentProvide就做这三步准备即可:

第一步,自定义SQLiteOpenHelper,创建表

第二步,自定义provider,集成增删该查方法

第三步,provider是组件,所以要想使用需要在清单配置文件中去配置

这些都做好以后就可以在activity,service,receiver中进行调用了,举个例子

 ContentResolver resolver = getContentResolver();

        ContentValues values = new ContentValues();
        for (int i = 0; i < 2; i++) {
            values.put(CustomProvider.COLUME_NAME, i);
            values.put(CustomProvider.COLUMN_AGE, i);
            resolver.insert(Uri.parse("content://" + CustomProvider.AUTHORITY + "/" + CustomProvider.TABLE), values);
        }

这是往表中插入两条数据,也可以进行数据的查询:

 cursor = resolver.query(Uri.parse("content://" + CustomProvider.AUTHORITY + "/" + CustomProvider.TABLE + "/2"), null, null, null, null);
        List<StudentBean> studentBean = new ArrayList<>();
        if (cursor != null) {
           while(cursor.moveToNext()) {
                StudentBean student = null;
                int nameIndex = cursor.getColumnIndexOrThrow(CustomProvider.COLUME_NAME);
                int ageIndex = cursor.getColumnIndexOrThrow(CustomProvider.COLUMN_AGE);
                int id = cursor.getColumnIndexOrThrow(CustomProvider.COLUME_ID);

                String name = cursor.getString(nameIndex);
                String age = cursor.getString(ageIndex);
                Log.i("fang",name);
                Log.i("fang",age);
                student = new StudentBean(name, age);
                studentBean.add(student);
            }


            cursor.close();

可以发现要想去使用contentprovider中集成好的方法,需要两步

第一:获取一个contentResolver对象:getCOntentResolver()方法

第二:在调用方法是传入一个uri:这个uri拼起来就是content://customProvidr/student/#,也就是content://域名/表名/要查询的列。

可以看到这样集成在每次调用时会超级麻烦,还不如自己集成的,所以如果是一个应用之间数据增删该查,不建议你使用contentProvider

如果看过我以前的博客的可以发现我早在半年前就打算去总结一个contentprovider的用法,但一直拖延着,眼高手低,内心着实羞愧,作为一个程序员,这样的做法很危险,谨以此文鼓励,铭记。

只有使用过才能明白使用环境,使用方法,以及这样做有什么不足。同时也给目前正在看视频只知道动脑或动眼而不愿动手的人一个小小建议

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏生信技能树

下载TCGA所有癌症的maf文件做signature分析

才sanger研究所已经做好了这个分析,但是值得我们重复一下,效果如下: ? TCGA所有癌症的mutation signature 首先TCGA所有癌症的ma...

926120
来自专栏wannshan(javaer,RPC)

ConcurrentHashMap 锁分段 源码分析

看ConcurrentHashMap下几个属性: /** * The default concurrency level for this table...

43360
来自专栏Python小屋

Python列表模拟页面调度LRU算法(京东2016笔试题)

问题描述:一进程刚获得3个主存块的使用权,若该进程访问页面的次序是1, 2, 3, 4, 1, 2, 5, 1, 2, 3, 4, 5。当采用LRU算法时,发生...

38750
来自专栏Android学习之路

ContentProvider

24290
来自专栏GIS讲堂

Arcgis4js实现链家找房的效果

买房的各位亲们不知是否留意过链家的"地图找房",这样的功能对于使用者来说,是非常方便的,大家可通过连接(https://bj.lianjia.com/ditu/...

15420
来自专栏指尖下的Android

Android面向切面AOP架构设计简析

按照惯例,谈一个框架时我们先说明一下这东西到底是啥、干什么的,首先AOP面向切面和我们通常意义上写的代码不太一样,Java是OOP面向对象,所有的代码都是符合某...

15230
来自专栏JAVA后端开发

解决spring boot无法捕捉404异常问题

但是在使用过程中,发现404时,根本没办法进入到该异常处理。经查,是spring mvc 在异常时,没有抛出404异常。 处理办法如下:

1K20
来自专栏Android干货

安卓开发_数据存储技术_sqlite

31370
来自专栏木宛城主

Unity应用架构设计(1)—— MVVM 模式的设计和实施(Part 1)

初识 MVVM 谈起 MVVM 设计模式,可能第一映像你会想到 WPF/Sliverlight,他们提供了的数据绑定(Data Binding),命令(Comm...

38260
来自专栏人工智能LeadAI

实时Android语音对讲系统架构

本文属于Android局域网内的语音对讲项目(https://github.com/yhthu/intercom)系列,《通过UDP广播实现Android局域网...

1.6K40

扫码关注云+社区

领取腾讯云代金券