多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > php開源 > 綜合技術 > 自定義ContentProvider

自定義ContentProvider

來源:程序員人生   發布時間:2016-11-19 14:52:14 閱讀次數:2691次

當多個利用程序同享同1數據時,我們可以給這個數據定義1個URI,然后把這個URI以接口的情勢暴漏出去,以后其他利用程序對此數據進行增刪改查時,只需要從當前上下文對象取得1個ContentResolver(內容解析器)傳入相應的URI就能夠了。數據庫支持直接操作db文件,問甚么還要用內容提供人?這是出于安全的斟酌,內容提供者可以根據自己的意愿選擇性的提供數據給客戶端使用。

(1)、操作步驟:

1、編寫1個類,讓其繼承自ContentProvider類;

2、實現ContentProvider類中所有的抽象方法;需要實現:onCreate() 、getType() 、query() 、insert() 、update()、delete() 等方法。

3、定義ContentProvider的Uri。這個Uri是ContentResolver對象履行CRUD操作時重要的參數;

4、使用UriMatcher對象映照Uri返回代碼;

5、在AndroidMainfest.xml文件中使用<provider>標簽注冊ContentProvider。

備注:

ContentProvider暴露出來的數據和方法其實不是給本身調用的,而是給其他利用程序來調用。其他利用程序通過其ContentResolver對象調用的query() 、insert() 、update()、delete() 等方法就是我們在這里暴露出來的ContentProvider類中的重寫后的query() 、insert() 、update()、delete() 方法。


(2)、ContentProvider類中的6個抽象方法:

1、boolean  onCreate()

2、Uri  insert(Uri  uri, ContentValues  values)

3、int  delete(Uri  uri, String selection, String[]  selectionArgs)

4、int  update(Uri  uri, ContentValues values, String  selection, String[]  selectionArgs)

5、Cursor  query(Uri  uri, String[]  projection, String  selection, String[]  selectionArgs, String  sortOrder)

6、String  getType(Uri  uri)


(3)、ContentProvider類中6個抽象方法的說明:

1、onCreate() 初始化provider

2、query() 返回數據給調用者

3、insert() 插入新數據到ContentProvider

4、update() 更新ContentProvider已存在的數據

5、delete() 從ContentProvider中刪除數據

6、getType() 返回ContentProvider數據的Mime類型


(4)、在清單文件中聲明注冊ContentProvider:

<provider android:name=".MyWordsProvider"
android:authorities="com.steven.wordscontentprovider"
android:exported="true" />
//android:name 屬性的值是:ContentProvider類的子類的完全路徑;
//android:authorities 屬性的值是:content:URI中authority部份。1般就是將name屬性的值全小寫。
//android:exported 屬性是不是允許其他利用調用。如果是false,則該ContentProvider不允許其他利用調用。

(5)、UriMatcher:
繼承ContentProvider類后發現,ContentProvider類中只有1個onCreate()生命周期方法——當其他利用程序通過ContentResolver第1次訪問ContentProvider時,onCreate()會被回調。
其他利用在通過ContentResolver對象履行CRUD操作時,都需要1個重要的參數Uri。為了能順利提供這個Uri參數,Android系統提供了1個UriMatcher工具類。

UriMatcher工具類提供了兩個方法:
1、void addURI(String authority , String path , int code) : 該方法用于向UriMatcher對象注冊Uri。其中authority和path是Uri中的重要部份。而code代表該Uri對應的標示符。
2、int match(Uri uri) : 根據注冊的Uri來判斷指定的Uri對應的標示符。如果找不到匹配的標示符,該方法返回⑴。
private static UriMatcher matcher = null;
static {

// 定義1個Uri匹配器。將UriMatcher.NO_MATCH,即⑴作為參數。
matcher = new UriMatcher(UriMatcher.NO_MATCH);
// 定義1組匹配規則
matcher.addURI(AUTHORITY, "words", 1);
matcher.addURI(AUTHORITY, "newwords", 2);
}
備注:
ContentProvider是單例模式的,當多個利用程序通過使用ContentResolver 來操作使用ContentProvider 提供的數據時,ContentResolver 調用的數據操作會拜托給同1個ContentProvider 來處理。這樣就可以保證數據的1致性。

(6)下面通過1個實例來說解自定義ContentProvider,需要創建兩個工程,1個工程用來自定義ContentProvider,然后把uri在程序清單中暴漏出去,那末此工程就相當于1個服務器端,可以供其他的工程來訪問其數據;另外1個工程相當于客戶端,通過使用ContentResolver 來操作使用ContentProvider 提供的數據。在測試時要先啟動服務端,再啟動客服端。

1,自定義ContentProvider的工程:

①創建1個繼承ContentProvider類:

package com.qf.mycontentprovide; 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.support.annotation.Nullable; /** * 多個利用共用同1個數據庫數據庫就是1個db文件 * 數據庫支持直接操作db文件,為何還要用內容提供者? * 答:出于安全的斟酌,內容提供者可以根據的自己的意愿選擇性的提供數據給客戶端使用。 * * 服務器和客戶端,安卓有jdbc的api,意味著安卓是可以直接訪問數據庫的, * 但是實際中我們使用接口訪問遠程服務器,這個接口提供給數據給我們的同時也是對遠程數據庫提供了保護, * 可以選擇性的返回數據給客戶端 */ public class MyContentProvider extends ContentProvider{ private SQLiteDatabase database; private UriMatcher uriMatcher; /** * 安裝以后會履行,以后app啟動不會履行 * 并且利用沒有啟動的時候,其他利用也是可以訪問自己提供的數據的 * 和數據庫的openhelper中的oncreate不1樣,數據庫是卸載再安裝才會履行, * 而MyContentProvider只要重新安裝就會履行 */ @Override public boolean onCreate() { DbHelper dbHelper = new DbHelper(getContext()); database = dbHelper.getReadableDatabase(); //獲得到1個uri匹配對象 uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); /** * addURI是把authority和path進行拼接 * code是給path設置了1個id */ uriMatcher.addURI("com.qf.mycontentprovide.MyContentProvider","person",1); uriMatcher.addURI("com.qf.mycontentprovide.MyContentProvider","teacher",2); return true; } /** * 操作數據庫時,由于數據庫有多張表,需要判斷操作那張表, * 這時候addURI的參數code就有了用武之地 */ @Nullable @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { Cursor cursor = null; int match = uriMatcher.match(uri); switch (match){ //person表 case 1: cursor = database.query("person", projection, selection, selectionArgs, null, null, sortOrder); break; //teacher表 case 2: cursor = database.query("teacher", projection, selection, selectionArgs, null, null, sortOrder); break; default: break; } return cursor; } /** * ContentValues里封裝了1個HashMap<String, Object> mValues; * 和普通的map的區分:鍵只能為string * @param uri 客戶端傳過來的uri路徑 * @param values 客戶端封裝的數據傳過來 * @return */ @Nullable @Override public Uri insert(Uri uri, ContentValues values) { int match = uriMatcher.match(uri); long num = 0; //插入數據受影響的行數 switch (match){ case 1: num = database.insert("person", null, values); break; case 2: num = database.insert("teacher",null,values); break; default: break; } //把受影響的行數拼接到uri后面 Uri uri1 = ContentUris.withAppendedId(uri, num); return uri1; } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { int match = uriMatcher.match(uri); int num = 0; switch (match){ case 1: num = database.delete("person", selection, selectionArgs); break; case 2: num = database.delete("person", selection, selectionArgs); break; } return num; } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { int match = uriMatcher.match(uri); int num = 0; switch (match){ case 1: num = database.update("person", values, selection, selectionArgs); break; case 2: num = database.update("teacher",values,selection,selectionArgs); break; } return num; } @Nullable @Override public String getType(Uri uri) { return null; } }


②創建1個數據庫操作類,用來向外提供數據:

package com.qf.mycontentprovide; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; /** * Created by Administrator on 2016/9/20. * 支持內容提供者向外提供數據的數據庫 */ public class DbHelper extends SQLiteOpenHelper { public DbHelper(Context context) { super(context, "Person.db", null, 2); } /** * 創建數據庫時創建1張person表,并給表初始化1條數據 */ @Override public void onCreate(SQLiteDatabase db) { db.execSQL("create table person(_id integer primary key autoincrement,name text,pass text)"); db.execSQL("insert into person(name,pass)values('張飛','123')"); } /** * 更新數據庫時,再創建1張teacher表,并初始化1條數據 */ @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { db.execSQL("create table teacher(_id integer primary key autoincrement,name text,pass text)"); db.execSQL("insert into person(name,pass)values('老張','12334')"); } }

③在清單文件中暴漏此內容提供者:

<span style="color:#464646;"><?xml version="1.0" encoding="utf⑻"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.qf.mycontentprovide"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <!-- authorities:向外提供數據的接口,即uri,1般為包名+類名 exported:是不是支持其他利用訪問自己的數據,設置為true --> </span><span style="color:#ff0000;"><provider android:authorities="com.qf.mycontentprovide.MyContentProvider" android:name=".MyContentProvider" android:exported="true"> </provider></span><span style="color:#464646;"> </application> </manifest></span>
由于MainActivity和activity_main.xml中不需要寫代碼,所以就不再給出。


2.再創建1個去同享內容提供者中的數據的工程:

①布局文件activity_main.xml中的代碼:

<?xml version="1.0" encoding="utf⑻"?> <LinearLayout 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" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:orientation="vertical" tools:context="com.example.client.MainActivity"> <Button android:id="@+id/query_person" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="查詢person表" /> <Button android:id="@+id/query_teacher" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="查詢teacher表" /> <Button android:id="@+id/insert_person" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="插入數據到person表" /> <Button android:id="@+id/insert_teacher" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="插入數據到teacher表" /> <Button android:id="@+id/delete_person" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="刪除person表中的數據" /> <Button android:id="@+id/delete_teacher" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="刪除teacher表中的數據" /> <Button android:id="@+id/updata_person" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="修改person表中的數據" /> <Button android:id="@+id/updata_teacher" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="修改teacher表中的數據" /> </LinearLayout>


②MainActivity中的代碼:

package com.example.client; import android.content.ContentResolver; import android.content.ContentUris; import android.content.ContentValues; import android.content.UriMatcher; import android.database.Cursor; import android.net.Uri; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.View; public class MainActivity extends AppCompatActivity implements View.OnClickListener { private ContentResolver contentResolver; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //初始化控件,并給控件設置監聽 findViewById(R.id.query_person).setOnClickListener(this); findViewById(R.id.query_teacher).setOnClickListener(this); findViewById(R.id.insert_person).setOnClickListener(this); findViewById(R.id.insert_teacher).setOnClickListener(this); findViewById(R.id.delete_person).setOnClickListener(this); findViewById(R.id.delete_teacher).setOnClickListener(this); findViewById(R.id.updata_person).setOnClickListener(this); findViewById(R.id.updata_teacher).setOnClickListener(this); //取得ContentResolver對象來操作數據庫 contentResolver = getContentResolver(); } @Override public void onClick(View v) { //person表的uri Uri personUri = Uri.parse("content://com.qf.mycontentprovide.MyContentProvider/person"); //teacher表的uri Uri teacherUri = Uri.parse("content://com.qf.mycontentprovide.MyContentProvider/teacher"); switch (v.getId()){ //查詢person表 case R.id.query_person: Cursor cursor = contentResolver.query(personUri, new String[]{"name", "pass"}, null, null, null,null); while(cursor.moveToNext()){ String name = cursor.getString(cursor.getColumnIndex("name")); String pass = cursor.getString(cursor.getColumnIndex("pass")); Log.e("name",name); Log.e("pass",pass); } break; //查詢teacher表 case R.id.query_teacher: Cursor cursor2 = contentResolver.query(teacherUri, new String[]{"name", "pass"}, null, null, null,null); while(cursor2.moveToNext()){ String name = cursor2.getString(cursor2.getColumnIndex("name")); String pass = cursor2.getString(cursor2.getColumnIndex("pass")); Log.e("name",name); Log.e("pass",pass); } break; case R.id.insert_person: ContentValues values = new ContentValues(); values.put("name","關羽"); values.put("pass","456"); Uri insert = contentResolver.insert(personUri, values); long num = ContentUris.parseId(insert); Log.e("num",num + ""); break; case R.id.insert_teacher: ContentValues values2 = new ContentValues(); values2.put("name","曹操"); values2.put("pass","321"); Uri insert2 = contentResolver.insert(teacherUri, values2); long num2 = ContentUris.parseId(insert2); Log.e("num",num2 + ""); break; case R.id.delete_person: int num3 = contentResolver.delete(personUri, "name = ?", new String[]{"張飛"}); Log.e("num3",num3 + ""); break; case R.id.delete_teacher: int num4 = contentResolver.delete(teacherUri, "name = ?", new String[]{"老張"}); Log.e("num4",num4 + ""); break; case R.id.updata_person: ContentValues values3 = new ContentValues(); values3.put("name","關羽"); values3.put("pass","789"); int num5 = contentResolver.update(personUri, values3, null, null); Log.e("num5",num5 + ""); break; case R.id.updata_teacher: ContentValues values4 = new ContentValues(); values4.put("name","曹操"); values4.put("pass","246"); int num6 = contentResolver.update(personUri, values4, null, null); Log.e("num6",num6 + ""); break; } } }









生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: 黄色aa大片 | 欧美高清网站 | xh98hx国产免费 | 欧美一级精品高清在线观看 | 国产日韩高清一区二区三区 | 激情 黄 +色+成+人 | 97精品国产综合久久久久久欧美 | 毛片破处| 国产粉嫩00福利福利福利 | 久久精品免观看国产成人 | 免费簧网站永久在线播放国产 | 成人在线视频网站 | 成年人在线观看免费视频 | 五月天看片 | 看片福利 | 欧美性在线观看 | 亚洲成a人不卡在线观看 | 男女视频在线观看免费 | 色亚洲影院 | 国产精品v欧美精品v日本精 | 国内久久精品视频 | 成 黄 色 激 情视频网站 | 久久青娱乐 | 欧美videosfree性喷潮 | 国产精品亚洲一区二区三区 | 高清在线亚洲精品国产二区 | 欧美一级淫片漂亮的老师 | 看欧美毛片一级毛片 | 亚洲黄色片网站 | 久久久欧美综合久久久久 | 亚洲国产大片 | 国产不卡一区二区三区免费视 | 在线观看视频网站 | 欧美一区二区在线免费观看 | 国产精品反差婊在线观看 | 国农村精品国产自线拍 | 精品欧美成人高清在线观看2021 | 国产一区二区三区亚洲欧美 | 久操视频网站 | 小说区 图片区 | 午夜羞羞视频 |