一篇就够了系列之ContentProvider全解析

xiaoxiao2021-02-28  111

前言:

上一篇介绍广播接收者(BroadcastReceover),本篇继续,记叙下Android四大组件最后一个不常用,但是非常有用的ContentProvider。Google文档

本文主要从以下几个方面介绍:

特点优缺点数据访问创建内容提供器工作机制

特点

Android四大组件之一,需要进行注册,一般有name,authorities,export等属性是一种定义数据共享的接口,并是不android数据存储的方式之一跨进程数据访问android系统很多系统应用都是使用ContentProvider方式进行储存的(图片,通讯录,视频,音频等)数据更新监听方便

优缺点

优点:

为数据访问提供统一的接口,解决了不同储存方式需要不同的API的访问所带来的繁琐跨进程数据的访问,实现了不同App数据访问提供了很大的便利

缺点:

不能单独使用,必须需要和其他的储存方式结合使用

数据访问

下面示例如何获取通讯录信息: Activity:

public class ContentProviderActivity extends AppCompatActivity { private ContentResolver mContentResolver;// StringBuilder builder=new StringBuilder(""); TextView tv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_content_provider); mContentResolver=getContentResolver(); tv= (TextView) findViewById(R.id.tv_show_contract); findViewById(R.id.tv_press_contract).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //动态申请权限 if(ContextCompat.checkSelfPermission(ContentProviderActivity.this, android.Manifest.permission.READ_CONTACTS)!= PackageManager.PERMISSION_GRANTED){ ActivityCompat.requestPermissions(ContentProviderActivity.this,new String[]{Manifest.permission.READ_CONTACTS},1); }else{ readContacts(); } } }); } private void readContacts(){ Cursor cursor=null; try { cursor=mContentResolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,null,null,null,null); if(cursor!=null){ while(cursor.moveToNext()){ String displayName=cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)); String number=cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)); builder.append(displayName); builder.append(": "); builder.append(number); builder.append(" "); Log.i("wy",displayName+" "+number); } } }catch (Exception e){ e.printStackTrace(); }finally { if(cursor!=null){ cursor.close(); } tv.setText(builder); } } }

以上:

借助ContentResolver类访问内容提供器中共享的数据,其提供了一系列的增删改查(CRUD)操作,其中insert方法用于添加数据,update更新数据,delete删除数据,query用于查询数据。和SQLiteDatabase类似,只是参数上稍微有些区别,ContentResolver中接收的参数是不接收表名参数的,而是使用一个Uri参数代码(关于Uri内容欢迎参考一篇就够了系列之Activity全解析中关于Scheme的介绍)。由于联系人信息是危险权限,所以需要动态申请,同时manifest中也需要申明代码中的查询等方法可以看到是个常量,其实也源码的一个封装。

创建内容提供器

public class MyContentProvider extends ContentProvider { public static final int DIR1=0; public static final int ITEM1=1; public static final int DIR2=2; public static final int ITEM2=3; public static final String AUTHRITY="com.wenyi.interview.provider"; private static UriMatcher uriMatcher; private MyDatabaseHelper dbhelper; static { uriMatcher=new UriMatcher(UriMatcher.NO_MATCH); uriMatcher.addURI(AUTHRITY,"book",DIR1); uriMatcher.addURI(AUTHRITY,"book/#",ITEM1); uriMatcher.addURI(AUTHRITY,"category",DIR2); uriMatcher.addURI(AUTHRITY,"category/#",ITEM2); } /** * 初始化内容提供器的时候调用,通常会在这里完成对数据库的创建和升级等操作 * @return true表示初始化成功,false表示初始化失败 * 只有当contentResolver尝试访问我们的程序中的数据是,内容提供器才会被初始化 */ @Override public boolean onCreate() { dbhelper=new MyDatabaseHelper(getContext(),"MyStore.db",null,2); return true; } /** * 查询数据 * @param uri 确定查询哪张表 * @param projection 确定查询哪些列 * @param selection 约束查询哪些行 * @param selectionArgs 约束查询哪些行 * @param sortOrder 用于对结果进行排序,查询的结果存放在Cursor对象中返回 * @return */ @Nullable @Override public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) { SQLiteDatabase db=dbhelper.getReadableDatabase(); Cursor cursor=null; switch (uriMatcher.match(uri)){ case DIR1: cursor=db.query("Book",projection,selection,selectionArgs,null,null,sortOrder); break; case ITEM1: String bookid=uri.getPathSegments().get(1); cursor=db.query("Book",projection,"id=?",new String[]{bookid},null,null,sortOrder); break; case DIR2: cursor=db.query("Category",projection,selection,selectionArgs,null,null,sortOrder); break; case ITEM2: String categoryid=uri.getPathSegments().get(1); cursor=db.query("Category",projection,"id=?",new String[]{categoryid},null,null,sortOrder); break; default: break; } return cursor; } /** * * @param uri * @return 传入的内容URI来返回相应的MIME类型 */ @Nullable @Override public String getType(@NonNull Uri uri) { switch (uriMatcher.match(uri)){ case DIR1: return "vnd.android.cursor.dir/vnd.com.wenyi.interview.provider.book"; case ITEM1: return "vnd.android.cursor.item/vnd.com.wenyi.interview.provider.book"; case DIR2: return "vnd.android.cursor.dir/vnd.com.wenyi.interview.provider.category"; case ITEM2: return "vnd.android.cursor.item/vnd.com.wenyi.interview.provider.category"; default: break; } return null; } /** * 添加数据 * @param uri 确定要添加到的表 * @param values 待添加的数据 * @return 添加完成后,返回一个用于表示这条心记录的URI */ @Nullable @Override public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) { return null; } /** * 删除数据 * @param uri 确定删除哪一张表中的数据 * @param selection 约束删除哪些行 * @param selectionArgs 约束删除哪些行 * @return 被删除的行 */ @Override public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) { return 0; } /** * 更新数据 * @param uri 更新的表 * @param values 新数据保存在其中 * @param selection 约束更新的行 * @param selectionArgs 约束更新的行 * @return 受影响的行作为返回值 */ @Override public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) { return 0; } }

代码有点长,现在来细细分析:

自定义MyContentProvider继承自ContentProvider,重写相应的方法,方法都有解释四个常量分别表示访问Book表中的说有数据,访问Book表中的单条数据,访问Category表中的所有数据和访问Category表中的单条数据在manifest中进行注册,<provider android:exported="true" android:enabled="true" android:authorities="com.wenyi.interview.provider" android:name=".FourComponet.contentProvider.MyContentProvider"/>代码中,UriMatche类,可以用来配皮Uri类型数据,其中,“*”和“#”分别表示匹配任意长度的任意字符和任意长度的数字。创建MyDatabaseHelper对象,继承自SQLiteOpenHelper,方便数据可操作,因为内容提供着只是接口标准,需要和数据存储方式结合使用只在query中写了相应代码,其他方法也需要写类似代码getType方法中,返回值很奇特。实际上,这是MIME字符格式,MIME主要由3部分组成,在Android中,格式为: a: 必须以vnd开头 b: 如果内容Uri以路径结尾,则后面接 android.cursor.dir/。如果内容Uri以id结尾,则后面接android.cursor.item/ c: 在最后面接 vnd.authority.path 这样,我们的内容提供器就创建完成了,通过这种机制,必须知道URI,才能顺利的访问该数据库中的内容,比保证了可访问,又保证了安全性。

工作机制

暂不分析

欢迎阅读其他系列文章:

一篇就够了系列之Activity全解析

一篇就够了系列之Service全解析

一篇就够了系列之BroadcastReceiver全解析

转载请注明原文地址: https://www.6miu.com/read-58272.html

最新回复(0)