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

说实话,我不知道这个工具类有什么存在的必要。。。了解了就行,用不用随意吧。

相关文章
相关标签/搜索