Android中ContentProvider基础应用的示例分析

Android中ContentProvider基础应用的示例分析

小编给大家分享一下Android中ContentProvider基础应用的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!

一、适用场景

1、ContentProvider为存储和读取数据提供了统一的接口

2、 使用ContentProvider,应用程序可以实现数据共享

3、 android内置的许多数据都是使用ContentProvider形式,供开发者调用的(如视频,音频,图片,通讯录等)

二、概念介绍

1、ContentProvider简介

当应用继承ContentProvider类,并重写该类用于提供数据和存储数据的方法,就可以向其他应用共享其数据。虽然使用其他方法也可以对外共享数据,但数据访问方式会因数据存储的方式而不同,如:采用文件方式对外共享数据,需要进行文件操作读写数据;采用sharedpreferences共享数据,需要使用sharedpreferences API读写数据。而使用ContentProvider共享数据的好处是统一了数据访问方式。

2、Uri类简介

Uri uri = Uri.parse("content://com.changcheng.provider.contactprovider/contact")

在Content Provider中使用的查询字符串有别于标准的SQL查询。很多诸如select, add, delete, modify等操作我们都使用一种特殊的URI来进行,这种URI由3个部分组成, “content://”, 代表数据的路径,和一个可选的标识数据的ID。以下是一些示例URI:

content://media/internal/images 这个URI将返回设备上存储的所有图片

content://contacts/people/ 这个URI将返回设备上的所有联系人信息

content://contacts/people/45 这个URI返回单个结果(联系人信息中ID为45的联系人记录)

尽管这种查询字符串格式很常见,但是它看起来还是有点令人迷惑。为此,Android提供一系列的帮助类(在android.provider包下),里面包含了很多以类变量形式给出的查询字符串,这种方式更容易让我们理解一点,因此,如上面content://contacts/people/45这个URI就可以写成如下形式:Uri person = ContentUris.withAppendedId(People.CONTENT_URI, 45)。

三、使用步骤

1、首先创建一个继承自ContentProvider的类,并实现其6个方法:

此6个方法只有onCreate方法运行在UI线程中,这里在onCreate方法中进行一些数据的初始化工作,初始了SQLite数据库【这里拿封装数据库操作举例,也可以是其他】,创建了两张表book、user 并分别默认插入了两本书,和两个管理员。

packagecom.hongri.androidipc.contentprovider;/***@authorzhongyao*@date2018/6/11**onCreate方法运行在主线程(main)中*其他方法运行在Binder线程池中**/publicclassMyContentProviderextendsContentProvider{privatestaticfinalStringTAG=MyContentProvider.class.getSimpleName()+"";/***唯一标识*/publicstaticfinalStringAUTHORITIES="com.hongri.androidipc.contentprovider.provider";publicstaticfinalUriBOOK_CONTENT_URI=Uri.parse("content://"+AUTHORITIES+"/book");publicstaticfinalUriUSER_CONTENT_URI=Uri.parse("content://"+AUTHORITIES+"/user");publicstaticfinalintBOOK_URI_CODE=0;publicstaticfinalintUSER_URI_CODE=1;privateDbOpenHelpermDbHelper;privateSQLiteDatabasemDB;privateContextmContext;privatestaticfinalUriMatchermUriMatcher=newUriMatcher(UriMatcher.NO_MATCH);static{mUriMatcher.addURI(AUTHORITIES,"book",BOOK_URI_CODE);mUriMatcher.addURI(AUTHORITIES,"user",USER_URI_CODE);}/***ContentProvider的创建:做一些初始化的工作*onCreate方法运行在主线程,其他方法运行在工作线程*@return*/@OverridepublicbooleanonCreate(){StringcurrentThreadName=Thread.currentThread().getName();Logger.d(TAG+"onCreate--"+"currentThreadName:"+currentThreadName);mContext=getContext();mDbHelper=newDbOpenHelper(getContext(),"",null,1);mDB=mDbHelper.getWritableDatabase();mDB.execSQL("deletefrom"+DbOpenHelper.BOOK_TABLE_NAME);mDB.execSQL("deletefrom"+DbOpenHelper.USER_TABLE_NAME);mDB.execSQL("insertintobookvalues('1','Android',234);");mDB.execSQL("insertintobookvalues('2','Java',348);");mDB.execSQL("insertintouservalues('1','hongri',1);");mDB.execSQL("insertintouservalues('2','huyin',1);");returntrue;}privateStringgetTableName(Uriuri){switch(mUriMatcher.match(uri)){caseBOOK_URI_CODE:returnDbOpenHelper.BOOK_TABLE_NAME;caseUSER_URI_CODE:returnDbOpenHelper.USER_TABLE_NAME;default:break;}return"";}/***用来返回一个MIME类型(媒体类型)**@paramuri*@return*/@Nullable@OverridepublicStringgetType(@NonNullUriuri){returnnull;}/***增**@paramuri*@paramvalues*@return*/@Nullable@OverridepublicUriinsert(@NonNullUriuri,@NullableContentValuesvalues){StringtableName=getTableName(uri);mDB.insert(tableName,null,values);mContext.getContentResolver().notifyChange(uri,null);returnuri;}/***删**@paramuri*@paramselection*@paramselectionArgs*@return*/@Overridepublicintdelete(@NonNullUriuri,@NullableStringselection,@NullableString[]selectionArgs){StringtableName=getTableName(uri);intcount=mDB.delete(tableName,selection,selectionArgs);if(count>0){mContext.getContentResolver().notifyChange(uri,null);}returncount;}/***查**@paramuri*@paramprojection*@paramselection*@paramselectionArgs*@paramsortOrder*@return*/@Nullable@OverridepublicCursorquery(@NonNullUriuri,@NullableString[]projection,@NullableStringselection,@NullableString[]selectionArgs,@NullableStringsortOrder){StringcurrentThreadName=Thread.currentThread().getName();Logger.d(TAG+"query:currentThreadName:"+currentThreadName+"uri:"+uri);StringtableName=getTableName(uri);returnmDB.query(tableName,projection,selection,selectionArgs,null,null,sortOrder,null);}/***改**@paramuri*@paramvalues*@paramselection*@paramselectionArgs*@return*/@Overridepublicintupdate(@NonNullUriuri,@NullableContentValuesvalues,@NullableStringselection,@NullableString[]selectionArgs){StringtableName=getTableName(uri);if(tableName==null){return0;}introw=mDB.update(tableName,values,selection,selectionArgs);if(row>0){mContext.getContentResolver().notifyChange(uri,null);}returnrow;}}

上面封装的 DbOpenHelper 代码如下:

packagecom.hongri.androidipc.db;/***@authorzhongyao*@date2018/6/11*/publicclassDbOpenHelperextendsSQLiteOpenHelper{publicstaticfinalStringBOOK_TABLE_NAME="book";publicstaticfinalStringUSER_TABLE_NAME="user";publicstaticfinalStringDB_NAME="library";publicstaticfinalintDB_VERSION=1;privateStringBOOK_SQL;privateStringUSER_SQL;publicDbOpenHelper(Contextcontext,Stringname,CursorFactoryfactory,intversion){super(context,DB_NAME,factory,DB_VERSION);BOOK_SQL="CREATETABLEIFNOTEXISTS"+BOOK_TABLE_NAME+"(_idINTEGERPRIMARYKEY,"+"nameTEXT,"+"pageINT)";USER_SQL="CREATETABLEIFNOTEXISTS"+USER_TABLE_NAME+"(_idINTEGERPRIMARYKEY,"+"nameTEXT,"+"sexINT)";}@OverridepublicvoidonCreate(SQLiteDatabasedb){db.execSQL(BOOK_SQL);db.execSQL(USER_SQL);}@OverridepublicvoidonUpgrade(SQLiteDatabasedb,intoldVersion,intnewVersion){}}

2、在Manifest文件中注册这个ContentProvider:

<providerandroid:name="com.hongri.androidipc.contentprovider.MyContentProvider"android:authorities="com.hongri.androidipc.contentprovider.provider"android:permission="com.hongri.androidipc.PROVIDER"android:process=":provider"/>

3、在外部应用中访问它:

<activityandroid:name=".ContentProviderActivity"android:process=":remoteProcess"><intent-filter><actionandroid:name="android.intent.action.MAIN"/><categoryandroid:name="android.intent.category.LAUNCHER"/></intent-filter></activity>

这里单独开启了一个进程 remoteProcess 用来模拟第三方App。

该Activity页面如下,点击相关按钮可以进行基础的增、删、查、改操作,可通过log查看调用结果。

这里注意如果希望监听数据更新,那么需要注册内容观察者 ContentObserver,增、删、改动的时候,会有回调通知,前提是在自定义的ContentProvider类方法中,调用getContentResolver().notifyChange(uri, null);方法即可。

packagecom.hongri.androidipc;/***@authorhongri*/publicclassContentProviderActivityextendsAppCompatActivityimplementsView.OnClickListener{//bookuriprivatefinalUribookUri=MyContentProvider.BOOK_CONTENT_URI;//useruriprivatefinalUriuserUri=MyContentProvider.USER_CONTENT_URI;privateButtonbtnInsert,btnQuery,btnQueryByUser,btnModify,btnDelete;privateHandlermHandler=newHandler();@OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_content_provider);btnInsert=(Button)findViewById(R.id.btnInsert);btnQuery=(Button)findViewById(R.id.btnQuery);btnQueryByUser=(Button)findViewById(R.id.btnQueryByUser);btnModify=(Button)findViewById(R.id.btnModify);btnDelete=(Button)findViewById(R.id.btnDelete);btnInsert.setOnClickListener(this);btnQuery.setOnClickListener(this);btnQueryByUser.setOnClickListener(this);btnModify.setOnClickListener(this);btnDelete.setOnClickListener(this);getContentResolver().registerContentObserver(bookUri,true,mContentObserver);getContentResolver().registerContentObserver(userUri,true,mContentObserver);}/***定义一个内容观察者【数据有更新时会调用】*/privateContentObservermContentObserver=newContentObserver(mHandler){@OverridepublicvoidonChange(booleanselfChange){super.onChange(selfChange);//这里selfChange都是返回false的,不用理会这个参数Logger.d("onChange调用---数据有更新");}};/***向bookUri中插入一本书*/privatevoiddoInsert(){ContentValuesvalues=newContentValues();values.put("name","Android框架");values.put("page","1213");Uriuri=getContentResolver().insert(bookUri,values);Logger.d("插入成功--->uri:"+uri.toString());}/***根据bookUri查询所有书籍*/privatevoiddoQuery(){CursorbookCursor=getContentResolver().query(bookUri,newString[]{"_id","name","page"},null,null,null);while(bookCursor.moveToNext()){Bookbook=newBook();book.set_id(bookCursor.getInt(0));book.setName(bookCursor.getString(1));book.setPage(bookCursor.getInt(2));Logger.d("book:"+book.toString());}bookCursor.close();}/***查询userUri所有图书员*/privatevoiddoQueryUser(){CursoruserCursor=getContentResolver().query(userUri,newString[]{"_id","name","sex"},null,null,null);while(userCursor.moveToNext()){Useruser=newUser();user.set_id(userCursor.getInt(0));user.setName(userCursor.getString(1));user.setSex(userCursor.getInt(2));Logger.d("user:"+user.toString());}userCursor.close();}/***更新书籍【Android底层开发】*/privatevoiddoUpdate(){ContentValuesupdateValues=newContentValues();updateValues.put("name","Android底层开发");updateValues.put("page",3345);introw=getContentResolver().update(bookUri,updateValues,"name=?",newString[]{"Android框架"});if(row>0){Logger.d("book:已修改");}}/***删除名为"Java"这本书*/privatevoiddoDelete(){intcount=getContentResolver().delete(bookUri,"name=?",newString[]{"Java"});if(count>0){Logger.d("book:已进行删除操作");}}@SuppressLint("NonConstantResourceId")@OverridepublicvoidonClick(Viewv){intid=v.getId();switch(id){caseR.id.btnInsert:/***增*/doInsert();break;caseR.id.btnQuery:/***查*/doQuery();break;caseR.id.btnQueryByUser:/***查*/doQueryUser();break;caseR.id.btnModify:/***改*/doUpdate();doQuery();break;caseR.id.btnDelete:/***删*/doDelete();doQuery();break;default:break;}}@OverrideprotectedvoidonDestroy(){super.onDestroy();getContentResolver().unregisterContentObserver(mContentObserver);}}

以上是“Android中ContentProvider基础应用的示例分析”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注恰卡编程网行业资讯频道!

发布于 2021-12-22 21:55:59
收藏
分享
海报
0 条评论
40
上一篇:绘制UML图时应避免的问题有哪些 下一篇:Android如何定义列表点击事件
目录

    推荐阅读

    0 条评论

    本站已关闭游客评论,请登录或者注册后再评论吧~

    忘记密码?

    图形验证码