Android四大組件之一:ContentProvider

一、ContentProvider是什麼?java

ContentProvider是安卓平臺中,在不一樣應用程序之間實現數據共享的一種機制。一個應用程序若是須要讓別的程序能夠操做本身的數據,便可採用這種機制。android

二、ContentProvider能作什麼事?sql

共享數據:好比短信應用就共享了全部短信的數據,咱們能夠用代碼操做這些數據,以下:數據庫

getContentResolver().query(Uri.parse("content://sms/inbox");

三、ContentProvider要怎麼用?ide

這裏以一個簡單的demo來演示用法。工具

(1)新建程序A,在程序A中新建一個類繼承ContentProviderspa

public class MyProvider extends ContentProvider{
	
	static final String TABLE_NAME = "test";
	static final String ID = "id";
	static final String CONTENT = "content";

	@Override
	public boolean onCreate() {
		SQL.addTable(TABLE_NAME, ID, CONTENT);
		SQL sql = SQL.init(getContext());
		sql.createTable();
		sql.insert(TABLE_NAME, "001", "NeiRon");
		return true;
	}

	@Override
	public Cursor query(Uri uri, String[] projection, String selection,
			String[] selectionArgs, String sortOrder) {
		SQL sql = SQL.init(getContext());
		Cursor c = sql.query(TABLE_NAME, new String[]{ID}, new String[]{"001"});
		return c;
	}
	
}

這個ContentProvider在初始化的時候新建了一個數據庫,而且新建了一張表,插入了一行數據;code

調用query查詢的時候我寫死了,直接查整張表;(懶)xml

SQL是我寫的一個數據庫工具類,比較懶就直接拖過來用了,不用在乎。
繼承

(2)在manifest中定義MyProvider

        <provider
            android:name="com.example.testb.MyProvider"
            android:authorities="com.linin.test"
            android:exported="true" >
        </provider>

android:authorities的參數能夠本身定義,只是個標識而已。

注意:android:exported="true"的意思是容許其餘程序調用本程序的MyProvider,默認是false;網上不少教程都沒提到這個,緣由是在2.3以前的系統不添加也能被其餘程序調用,不知道爲何,反正我是被這個坑慘了!QAQ

(3)新建程序B,在程序B中查詢MyProvider共享的數據;

注意Uri的格式是:content://自定義的標識[/表名][/ID]

自定義標識其實就是程序A的android:authorities;

表名=數據庫表名;ID=_id參數;

(若是不太熟悉的,建議去百度一下)

注意:實際上只要自定義標識對上了,就能調用MyProvider的query方法,以後就根據傳過來的Uri進行後續的操做;我這個demo由於沒對Uri作任何操做,形同虛設,因此怎麼傳都無所謂(保證content://com.linin.test開頭就行);

protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		TextView tv = (TextView) findViewById(R.id.text);
		
		ContentResolver cr = getContentResolver();
		Uri uri = Uri.parse("content://com.linin.test");
		Cursor c = cr.query(uri, null, null, null, null);
		if (c!=null&&c.moveToNext()) {
			tv.setText(c.getString(c.getColumnIndex(CONTENT)));
		}
		c.close();
		c = null;
	}

運行結果:在程序B中獲取到了程序A共享的數據,並顯示出來,以下:

四、一些其餘的東西?

網上的一些教程有提到UriMatcher、ContentUris這兩個工具類,其實吧,這兩個類其實無關緊要,一個是爲了判斷查詢所有表數據仍是查詢單條數據,一個是拼接Uri的。好吧,對於習慣用正則又喜歡字符串+字符串拼接的我來講沒太必要,不過仍是瞭解一下吧。

(1)UriMatcher,從名字就能夠看出這個工具類其實就是用了正則來判斷的。用法以下,在ContentProvider中初始化:

private static final UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
	static{
		uriMatcher.addURI("com.linin.test", "test", 0);//表明查詢整張test表
		uriMatcher.addURI("com.linin.test", "test/#", 1);//表明查詢test表的單條數據
	}

而後在getType中判斷Uri的數據類型:

public String getType(Uri uri) {
		Log.e("test","getType!!!"+uri.toString());
		int witch = uriMatcher.match(uri);
		switch (witch) {
		case 0://查詢整張表
			return "vnd.android.cursor.dir/test";
		case 1://查詢單條數據
			return "vnd.android.cursor.item/test";
		}
		return null;
	}

那麼問題就來了:咱們何時要用到這個getType呢?

實際上,我在程序B中獲取到程序A的共享數據後,getType一次也沒被調用。

其實只要在程序B中把getContentResolver().getType(uri)打印出來就知道了,ContentResolver中的getType會根據傳入的Uri與每一個ContentProvider匹配,匹配後調用其getType獲取該數據類型。

那麼問題又來了:這樣作有什麼意義?

好吧其實意義不大。到這裏其實我已經醉了,網上的教程對getType的說法模糊不清,越看越亂。接下來我就以我本身的理解來介紹下getType吧!

看我寫的代碼就知道了,getType的做用只有一個,就是返回數據的類型,返回類型的做用固然也只有一個,用來判斷!

因而咱們能夠在query方法中這樣寫:

public Cursor query(Uri uri, String[] projection, String selection,
			String[] selectionArgs, String sortOrder) {
		String type = getType(uri);
		if (type.equals("vnd.android.cursor.dir/test")) {
			//多行數據類型
		}else if (type.equals("vnd.android.cursor.item/test")) {
			//單行數據類型
		}
		return c;
	}

做用很明顯了,就是用來判斷數據類型的(多行or單行)!

一些聰明的小夥伴可能發現了:那我直接把getType裏面的判斷搬出來不就好了?

嗯。。。確實在MyProvider裏面是能夠這樣寫,不過也得考慮其餘狀況,好比說在個人程序B中,若是不用getContentResolver().getType(uri)去獲取數據類型的話,那我就又要初始化一次UriMatcher了,畢竟UriMatcher的初始化是在程序A的MyProvider中完成的。


呼呼呼,總算強行解釋通了~~


(2)ContentUris,一個神奇的工具,他能夠作到這樣:

Uri uri = Uri.parse("content://com.linin.test/test");
		Uri resultUri = ContentUris.withAppendedId(uri, 10);
		結果:
		resultUri-->content://com.linin.test/test/10
		等價於:
		Uri resultUri = Uri.parse("content://com.linin.test/test/10");

他也能夠作到這樣:

Uri uri = Uri.parse("content://com.linin.test/test/10");
		long id = ContentUris.parseId(uri);
		結果:
		id-->10

說實話,我不知道這個工具類有什麼存在的必要。。。瞭解了就行,用不用隨意吧。

相關文章
相關標籤/搜索