contentprovider的学习实例总结
工作中遇到了contentprovider数据共享机制,下面来总结一下: 一、ContentProvider简介 当应用继承ContentProvider类,并重写该类用于提供数据和存储数据的方法,就可以向其他应用共享其数据。虽然使用其他方法也可以对外共享数据,但数据访问方式会因数据存储的方式而不同,如:采用文件方式对外共享数据,需要进行文件操作读写数据;采用sharedpreferences共享数据,需要使用sharedpreferencesAPI读写数据。而使用ContentProvider共享数据的好处是统一了数据访问方式。 二、Uri类简介 Uri代表了要操作的数据,Uri主要包含了两部分信息:1.需要操作的ContentProvider,2.对ContentProvider中的什么数据进行操作,一个Uri由以下几部分组成: 1.scheme:ContentProvider(内容提供者)的scheme已经由Android所规定为:content://。 2.主机名(或Authority):用于唯一标识这个ContentProvider,外部调用者可以根据这个标识来找到它。 3.路径(path):可以用来表示我们要操作的数据,路径的构建应根据业务而定,如下: •要操作contact表中id为10的记录,可以构建这样的路径:/contact/10 •要操作contact表中id为10的记录的name字段,contact/10/name •要操作contact表中的所有记录,可以构建这样的路径:/contact 要操作的数据不一定来自数据库,也可以是文件等他存储方式,如下: 要操作xml文件中contact节点下的name节点,可以构建这样的路径:/contact/name 如果要把一个字符串转换成Uri,可以使用Uri类中的parse()方法,如下: Uriuri=Uri.parse("content://com.changcheng.provider.contactprovider/contact") 三、UriMatcher、ContentUrist和ContentResolver简介 因为Uri代表了要操作的数据,所以我们很经常需要解析Uri,并从Uri中获取数据。Android系统提供了两个用于操作Uri的工具类,分别为UriMatcher和ContentUris。掌握它们的使用,会便于我们的开发工作。 UriMatcher:用于匹配Uri,它的用法如下: 1.首先把你需要匹配Uri路径全部给注册上,如下: //常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码(-1)。 UriMatcheruriMatcher=newUriMatcher(UriMatcher.NO_MATCH); //如果match()方法匹配content://com.changcheng.sqlite.provider.contactprovider/contact路径,返回匹配码为1 uriMatcher.addURI(“com.changcheng.sqlite.provider.contactprovider”,“contact”,1);//添加需要匹配uri,如果匹配就会返回匹配码 //如果match()方法匹配content://com.changcheng.sqlite.provider.contactprovider/contact/230路径,返回匹配码为2 uriMatcher.addURI(“com.changcheng.sqlite.provider.contactprovider”,“contact/#”,2);//#号为通配符 2.注册完需要匹配的Uri后,就可以使用uriMatcher.match(uri)方法对输入的Uri进行匹配,如果匹配就返回匹配码,匹配码是调用addURI()方法传入的第三个参数,假设匹配content://com.changcheng.sqlite.provider.contactprovider/contact路径,返回的匹配码为1。 ContentUris:用于获取Uri路径后面的ID部分,它有两个比较实用的方法: •withAppendedId(uri,id)用于为路径加上ID部分 •parseId(uri)方法用于从路径中获取ID部分 ContentResolver:当外部应用需要对ContentProvider中的数据进行添加、删除、修改和查询操作时,可以使用ContentResolver类来完成,要获取ContentResolver对象,可以使用Activity提供的getContentResolver()方法。ContentResolver使用insert、delete、update、query方法,来操作数据。 四、ContentProvider示例程序 Manifest.xml中的代码: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <applicationandroid:icon= "@drawable/icon"android:label="@string/app_name"> <activityandroid:name= ".TestWebviewDemo"android:label="@string/app_name"> <intent-filter> <actionandroid:name= "android.intent.action.MAIN"/> <categoryandroid:name= "android.intent.category.LAUNCHER"/> </intent-filter> <intent-filter> <dataandroid:mimeType= "vnd.android.cursor.dir/vnd.ruixin.login"/> </intent-filter> <intent-filter> <dataandroid:mimeType= "vnd.android.cursor.item/vnd.ruixin.login"/> </intent-filter> </activity> <providerandroid:name= "MyProvider"android:authorities="com.ruixin.login"/> </application> 需要在<application></application>中为provider进行注册!!!! 首先定义一个数据库的工具类: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 publicclassRuiXin{ publicstaticfinalStringDBNAME="ruixinonlinedb"; publicstaticfinalStringTNAME="ruixinonline"; publicstaticfinalintVERSION=3; publicstaticStringTID="tid"; publicstaticfinalStringEMAIL="email"; publicstaticfinalStringUSERNAME="username"; publicstaticfinalStringDATE="date"; publicstaticfinalStringSEX="sex"; publicstaticfinalStringAUTOHORITY="com.ruixin.login"; publicstaticfinalintITEM=1; publicstaticfinalintITEM_ID=2; publicstaticfinalStringCONTENT_TYPE="vnd.android.cursor.dir/vnd.ruixin.login"; publicstaticfinalStringCONTENT_ITEM_TYPE="vnd.android.cursor.item/vnd.ruixin.login"; publicstaticfinalUriCONTENT_URI=Uri.parse( "content://" +AUTOHORITY+"/ruixinonline"); } 然后创建一个数据库: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 publicclassDBliteextendsSQLiteOpenHelper{ publicDBlite(Contextcontext){ super(context,RuiXin.DBNAME,null,RuiXin.VERSION); //TODOAuto-generatedconstructorstub } @Override publicvoidonCreate(SQLiteDatabasedb){ //TODOAuto-generatedmethodstub db.execSQL( "createtable"+RuiXin.TNAME+"("+ RuiXin.TID+"integerprimarykeyautoincrementnotnull,"+ RuiXin.EMAIL+ "textnotnull,"+ RuiXin.USERNAME+ "textnotnull,"+ RuiXin.DATE+"intergernotnull,"+ RuiXin.SEX+"textnotnull);"); } @Override publicvoidonUpgrade(SQLiteDatabasedb,intoldVersion,intnewVersion){ //TODOAuto-generatedmethodstub } publicvoidadd(Stringemail,Stringusername,Stringdate,Stringsex){ SQLiteDatabasedb=getWritableDatabase(); ContentValuesvalues= newContentValues(); values.put(RuiXin.EMAIL,email); values.put(RuiXin.USERNAME,username); values.put(RuiXin.DATE,date); values.put(RuiXin.SEX,sex); db.insert(RuiXin.TNAME,"",values); } } 接着创建一个Myprovider.java对数据库的接口进行包装: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 publicclassMyProviderextendsContentProvider{ DBlitedBlite; SQLiteDatabasedb; privatestaticfinalUriMatchersMatcher; static{ sMatcher= newUriMatcher(UriMatcher.NO_MATCH); sMatcher.addURI(RuiXin.AUTOHORITY,RuiXin.TNAME,RuiXin.ITEM); sMatcher.addURI(RuiXin.AUTOHORITY,RuiXin.TNAME+"/#",RuiXin.ITEM_ID); } @Override publicintdelete(Uriuri,Stringselection,String[]selectionArgs){ //TODOAuto-generatedmethodstub db=dBlite.getWritableDatabase(); intcount=0; switch(sMatcher.match(uri)){ caseRuiXin.ITEM: count=db.delete(RuiXin.TNAME,selection,selectionArgs); break; caseRuiXin.ITEM_ID: Stringid=uri.getPathSegments().get(1); count=db.delete(RuiXin.TID,RuiXin.TID+"="+id+(!TextUtils.isEmpty(RuiXin.TID="?")?"AND("+selection+')':""),selectionArgs); break; default: thrownewIllegalArgumentException("UnknownURI"+uri); } getContext().getContentResolver().notifyChange(uri,null); returncount; } @Override publicStringgetType(Uriuri){ //TODOAuto-generatedmethodstub switch(sMatcher.match(uri)){ caseRuiXin.ITEM: returnRuiXin.CONTENT_TYPE; caseRuiXin.ITEM_ID: returnRuiXin.CONTENT_ITEM_TYPE; default: thrownewIllegalArgumentException("UnknownURI"+uri); } } @Override publicUriinsert(Uriuri,ContentValuesvalues){ //TODOAuto-generatedmethodstub db=dBlite.getWritableDatabase(); longrowId; if(sMatcher.match(uri)!=RuiXin.ITEM){ thrownewIllegalArgumentException("UnknownURI"+uri); } rowId=db.insert(RuiXin.TNAME,RuiXin.TID,values); if(rowId>0){ UrinoteUri=ContentUris.withAppendedId(RuiXin.CONTENT_URI,rowId); getContext().getContentResolver().notifyChange(noteUri,null); returnnoteUri; } thrownewIllegalArgumentException("UnknownURI"+uri); } @Override publicbooleanonCreate(){ //TODOAuto-generatedmethodstub this.dBlite=newDBlite(this.getContext()); //db=dBlite.getWritableDatabase(); //return(db==null)?false:true; returntrue; } @Override publicCursorquery(Uriuri,String[]projection,Stringselection, String[]selectionArgs,StringsortOrder){ //TODOAuto-generatedmethodstub db=dBlite.getWritableDatabase(); Cursorc; Log.d("-------",String.valueOf(sMatcher.match(uri))); switch(sMatcher.match(uri)){ caseRuiXin.ITEM: c=db.query(RuiXin.TNAME,projection,selection,selectionArgs,null,null,null); break; caseRuiXin.ITEM_ID: Stringid=uri.getPathSegments().get(1); c=db.query(RuiXin.TNAME,projection,RuiXin.TID+"="+id+(!TextUtils.isEmpty(selection)?"AND("+selection+')':""),selectionArgs,null,null,sortOrder); break; default: Log.d("!!!!!!","UnknownURI"+uri); thrownewIllegalArgumentException("UnknownURI"+uri); } c.setNotificationUri(getContext().getContentResolver(),uri); returnc; } @Override publicintupdate(Uriuri,ContentValuesvalues,Stringselection, String[]selectionArgs){ //TODOAuto-generatedmethodstub return0; } } 最后创建测试类: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 publicclassTestextendsActivity{ /**Calledwhentheactivityisfirstcreated.*/ privateDBlitedBlite1=newDBlite(this);; privateContentResolvercontentResolver; publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.main); //先对数据库进行添加数据 dBlite1.add(email,username,date,sex); //通过contentResolver进行查找 contentResolver=TestWebviewDemo.this.getContentResolver(); Cursorcursor=contentResolver.query( RuiXin.CONTENT_URI, newString[]{ RuiXin.EMAIL,RuiXin.USERNAME, RuiXin.DATE,RuiXin.SEX},null,null,null); while(cursor.moveToNext()){ Toast.makeText( TestWebviewDemo.this, cursor.getString(cursor.getColumnIndex(RuiXin.EMAIL)) +"" +cursor.getString(cursor.getColumnIndex(RuiXin.USERNAME)) +"" +cursor.getString(cursor.getColumnIndex(RuiXin.DATE)) +"" +cursor.getString(cursor.getColumnIndex(RuiXin.SEX)), Toast.LENGTH_SHORT).show(); } startManagingCursor(cursor);//查找后关闭游标 } } 注:上面是在一个程序中进行的测试,也可以再新建一个工程来模拟一个新的程序,然后将上面查询的代码加到新的程序当中!这样就模拟了contentprovider的数据共享功能了! 新建个工程:TestProvider 创建一个测试的activity ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 publicclassTestextendsActivity{ /**Calledwhentheactivityisfirstcreated.*/ privateContentResolvercontentResolver; publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.main); //通过contentResolver进行查找 contentResolver=TestWebviewDemo.this.getContentResolver(); Cursorcursor=contentResolver.query( RuiXin.CONTENT_URI, newString[]{ RuiXin.EMAIL,RuiXin.USERNAME, RuiXin.DATE,RuiXin.SEX},null,null,null); while(cursor.moveToNext()){ Toast.makeText(TestWebviewDemo.this, cursor.getString(cursor.getColumnIndex(RuiXin.EMAIL)) +"" +cursor.getString(cursor.getColumnIndex(RuiXin.USERNAME)) +"" +cursor.getString(cursor.getColumnIndex(RuiXin.DATE)) +"" +cursor.getString(cursor.getColumnIndex(RuiXin.SEX)), Toast.LENGTH_SHORT).show(); } startManagingCursor(cursor);//查找后关闭游标 } } 运行此程序就能实现共享数据查询了! 注:新建的程序中的manifest.xml中不需要对provider进行注册,直接运行就行,否则会报错! 摘自:http://www.cnblogs.com/chenglong/articles/1892029.html 本文转自 wbb827 51CTO博客,原文链接:http://blog.51cto.com/wbb827/1243322