實例講解Android中ContentProvider組件的使用方法
ContentProvider基本使用
為了在應(yīng)用程序之間交換數(shù)據(jù),android提供了ContentProvider,ContentProvider是不同應(yīng)用程序之間進行數(shù)據(jù)交換的標準API,當一個應(yīng)用程序需要把自己的數(shù)據(jù)暴露給其他程序使用時,該應(yīng)用程序就可以通過提供ContentPRovider來實現(xiàn),其他應(yīng)用程序就可以通過ContentResolver來操作ContentProvider暴露的數(shù)據(jù)。
實現(xiàn)ContentProvider的步驟:
1)編寫一個類,繼承ContentProvider,并且重寫里面的CRUD方法。
2)在androidmanifest.xml文件中注冊provider。
在androidmanifest.xml中注冊provider需要以下3個屬性:
android:name provider的實現(xiàn)類。
android:authorities provider的uri。
android:exported provider是否暴露給其他程序。
ContentResovler操作ContentProvider:
1)獲取ContentResolver,getContentResovler()方法來自于ContextWrapper,所以activity和service中都可以使用。
2)調(diào)用CURD方法,通過參數(shù)url,調(diào)用指定的ContentProvider的方法。
下面是一個demo,向contentProvider中插入一條數(shù)據(jù),并且返回到listview中。
main.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".Main" > <ListView android:id="@+id/listview" android:layout_width="match_parent" android:layout_height="wrap_content" /> </RelativeLayout>
MySQLiteOpenHelper類
package com.app.dao; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase.CursorFactory; import android.database.sqlite.SQLiteOpenHelper; public class MySQLiteOpenHelper extends SQLiteOpenHelper { public MySQLiteOpenHelper(Context context, String name, CursorFactory factory, int version) { super(context, name, factory, version); } @Override public void onCreate(SQLiteDatabase db) { String create_sql = "create table tb_test(_id integer primary key autoincrement,name,gender,age)"; db.execSQL(create_sql); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } }
MyContentProvider類
package com.app.dao; import android.content.ContentProvider; import android.content.ContentValues; import android.database.Cursor; import android.net.Uri; public class MyContentProvider extends ContentProvider{ MySQLiteOpenHelper helper=null; @Override public int delete(Uri arg0, String arg1, String[] arg2) { return 0; } @Override public String getType(Uri arg0) { // TODO Auto-generated method stub return null; } @Override public Uri insert(Uri arg0, ContentValues values) { String insert_sql="insert into tb_test values(null,'wx','boy',17)"; helper.getReadableDatabase().execSQL(insert_sql); return null; } @Override public boolean onCreate() { helper=new MySQLiteOpenHelper(this.getContext(),"test.db3",null,1); return true; } @Override public Cursor query(Uri arg0, String[] arg1, String arg2, String[] arg3, String arg4) { String query_sql="select * from tb_test"; Cursor cursor=helper.getReadableDatabase().rawQuery(query_sql, null); return cursor; } @Override public int update(Uri arg0, ContentValues arg1, String arg2, String[] arg3) { // TODO Auto-generated method stub return 0; } }
listview的顯示界面show.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" > <TextView android:id="@+id/name" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:id="@+id/gender" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="60dp" /> <TextView android:id="@+id/age" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="60dp" /> </LinearLayout>
Main.java
package com.app.main; import android.annotation.SuppressLint; import android.app.Activity; import android.content.ContentResolver; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.support.v4.widget.CursorAdapter; import android.widget.ListView; import android.widget.SimpleCursorAdapter; public class Main extends Activity { ContentResolver resolver = null; ListView lv = null; @SuppressLint("NewApi") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); lv = (ListView) this.findViewById(R.id.listview); resolver = this.getContentResolver(); String str = "content://com.app.test.db/"; Uri uri = Uri.parse(str); resolver.insert(uri, null); Cursor cursor = resolver.query(uri, null, null, null, null); SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.show, cursor, new String[] { "name", "gender", "age" }, new int[] { R.id.name, R.id.gender, R.id.age }, CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER); lv.setAdapter(adapter); } }
實現(xiàn)效果:(執(zhí)行了3次插入后的效果)
ContentProvider的單元測試
ContentProvider是android的四大組件之一,在編寫代碼的時候最好是加上單元測試,這樣可以確定對數(shù)據(jù)的CRUD的正確。本篇文章主要介紹ContentProvider中兩個主要輔助類的使用還有單元測試的在ContentProvider中的使用。
需要用到的兩個輔助類:UriMatcher類和ContentUris類。
UriMatcher類:能夠?qū)斎氲膗ri參數(shù)就行匹配,以確定對什么表執(zhí)行什么樣的操作。
ContentUris類:有些方法需要返回uri,運用此類可以方便的生成uri類。
對于單元測試,個人覺得非常有必要在今后寫代碼的時候使用,這樣可以非常準確的確定代碼的正確性。
使用單元測試的步驟:
1)加入instrumentation,這個部分的代碼是固定,也可以完全在ADT提供的向?qū)е袑?dǎo)入。
<instrumentation android:name="android.test.InstrumentationTestRunner" android:targetPackage="com.example.android_contentprovider" > </instrumentation>
2)添加<uses-library>,這個部分的代碼也是固定的寫法。
<uses-library android:name="android.test.runner" />
好了,必備的知識已經(jīng)講完了,現(xiàn)在上代碼:
1)生成一個SQLiteDatabase類,這個是必需的類MySQLiteOpenHelper類
package com.app.db; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase.CursorFactory; import android.database.sqlite.SQLiteOpenHelper; public class MySQLiteOpenHelper extends SQLiteOpenHelper { private static String DB_NAME = "test.db3"; private static int VERSION = 1; public MySQLiteOpenHelper(Context context) { super(context, DB_NAME, null, VERSION); } @Override public void onCreate(SQLiteDatabase db) { //建表語句 String create_student = "create table student(_id integer primary key autoincrement,name varchar(10),age integer,gender vachar(10))"; db.execSQL(create_student); //千萬不能執(zhí)行這句 // db.close(); } @Override public void onUpgrade(SQLiteDatabase arg0, int arg1, int arg2) { } }
然后添加我們需要的MyContentProvider類:
package com.app.contentprovider; import com.app.db.MySQLiteOpenHelper; import android.content.ContentProvider; import android.content.ContentUris; import android.content.ContentValues; import android.content.UriMatcher; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.net.Uri; import android.util.Log; public class MyContentProvider extends ContentProvider { MySQLiteOpenHelper helper = null; private static UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH); // 匹配單條記錄 private static final int student = 1; // 匹配多條記錄 private static final int students = 2; static { matcher.addURI("com.app.wx", "student/#", student); matcher.addURI("com.app.wx", "student", students); } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { SQLiteDatabase db = helper.getWritableDatabase(); int action = matcher.match(uri); switch (action) { // 匹配單條記錄 case student: long id = ContentUris.parseId(uri); //獲取單條記錄的id號 String delete_id = "_id=" + id; if (selection != null) { delete_id += delete_id + " and " + selection; } db.delete("student", delete_id, selectionArgs); break; // 匹配多條記錄 case students: db.delete("student", selection, selectionArgs); break; } return 0; } //必需實現(xiàn)這個方法,這個方法與intent有關(guān)系,以后再講 @Override public String getType(Uri uri) { int code = matcher.match(uri); switch (code) { case student: return "vnd.android.cursor.item/student_item"; case students: return "vnd.android.cursor.dir/students"; default: return null; } } @Override public Uri insert(Uri uri, ContentValues values) { SQLiteDatabase db = helper.getWritableDatabase(); int action = matcher.match(uri); switch (action) { case students: long id1 = db.insert("student", "_id", values); Log.i("--------", ContentUris.withAppendedId(uri, id1).toString()); return ContentUris.withAppendedId(uri, id1); } return null; } @Override public boolean onCreate() { helper = new MySQLiteOpenHelper(this.getContext()); return true; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String orderBy) { SQLiteDatabase db = helper.getWritableDatabase(); Cursor cursor = null; int action = matcher.match(uri); switch (action) { case students: cursor = db.query("student", projection, selection, selectionArgs, null, null, orderBy); break; } System.out.println("-----------count:" + cursor.getCount()); return cursor; } @Override public int update(Uri uri, ContentValues values, String selection, String[] arg3) { int count = -1; SQLiteDatabase db = helper.getWritableDatabase(); int action = matcher.match(uri); switch (action) { case student: // 以id來處理更新 long id = ContentUris.parseId(uri); String id_selection = "_id=" + id; if (selection != null && !selection.equals("")) { id_selection = id_selection + " and " + values; } count = db.update("student", values, id_selection, arg3); System.out.println("----------count:" + count); break; } return count; } }
這個類很長,但是執(zhí)行的方法都是比較常見的CURD的方法,重要的是UriMatcher和ContentUris類的使用。
接著執(zhí)行單元測試類:Test
package com.app.contentprovider; import android.content.ContentResolver; import android.content.ContentValues; import android.database.Cursor; import android.net.Uri; import android.test.AndroidTestCase; import android.util.Log; public class Test extends AndroidTestCase { public void insert() { ContentResolver resolver = this.getContext().getContentResolver(); String str = "content://com.app.wx/student"; ContentValues values = new ContentValues(); values.put("name", "wzq"); values.put("age", 18); values.put("gender", "boy"); resolver.insert(Uri.parse(str), values); } public void update() { ContentResolver resolver = this.getContext().getContentResolver(); String str = "content://com.app.wx/student/2"; ContentValues values = new ContentValues(); values.put("name", "哈哈"); resolver.update(Uri.parse(str), values, null, null); } public void query() { ContentResolver resolver = this.getContext().getContentResolver(); String str = "content://com.app.wx/student"; Uri uri = Uri.parse(str); Cursor cursor = resolver.query(uri, new String[] { "_id", "name,age,gender" }, null, null, "_id desc"); Log.d("------count",cursor.getCount()+""); } public void delete() { ContentResolver resolver = this.getContext().getContentResolver(); String str = "content://com.app.wx/student/2"; Uri uri = Uri.parse(str); long id=resolver.delete(uri, null, null); } }
執(zhí)行insert方法之后(執(zhí)行了三次):
執(zhí)行了update方法之后:
執(zhí)行了query方法之后:
執(zhí)行了delete方法之后:
- Android應(yīng)用中使用ContentProvider掃描本地圖片并顯示
- Android中自定義ContentProvider實例
- Android開發(fā)之ContentProvider的使用詳解
- Android 自定義ContentProvider簡單實例
- Android數(shù)據(jù)持久化之ContentProvider機制詳解
- Android ContentProvider的實現(xiàn)及簡單實例代碼
- Android開發(fā)教程之ContentProvider數(shù)據(jù)存儲
- android基礎(chǔ)總結(jié)篇之八:創(chuàng)建及調(diào)用自己的ContentProvider
- Android學(xué)習(xí)筆記之ContentProvider和Uri詳解
- 詳解Android ContentProvider的基本原理和使用
相關(guān)文章
Flutter學(xué)習(xí)之SliverList和SliverGird的使用詳解
Sliver的組件一般都用在CustomScrollView中,除了SliverAppBar之外,我們還可以為CustomScrollView添加List或者Grid來實現(xiàn)更加復(fù)雜的組合效果。本文就來聊聊SliverList和SliverGird的使用吧2023-02-02Android自定義View實現(xiàn)仿駕考寶典顯示分數(shù)效果(收藏)
本文通過自定義view和屬性動畫結(jié)合在一起實現(xiàn)實現(xiàn)仿駕考寶典顯示分數(shù)效果,非常不錯,具有參考借鑒價值,需要的的朋友參考下2017-03-03Android仿微信右上角點擊加號彈出PopupWindow
這篇文章主要為大家詳細介紹了Android仿微信右上角點擊加號彈出PopupWindow,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-04-04Android 保存Fragment 切換狀態(tài)實例代碼
本文主要介紹Android Fragment的應(yīng)用,這里給大家用實例代碼詳細介紹了Android Fragment 切換狀態(tài),有需要的小伙伴可以參考下2016-07-07Android手勢密碼view學(xué)習(xí)筆記(一)
這篇文章主要為大家詳細介紹了Android手勢密碼view的學(xué)習(xí)筆記,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-03-03