使用ContentProvider进行应用程序间的数据交互

 

什么是ContentProvider:

        ContentProvider用来管理数据的访问规则。它允许你的应用程序向外界暴露需要被访问的数据。

是Android的四大组件之一。

        ContentProviders支持四种基本的操作,即我们平时所见到的CRUD操作(增删改查)。Android系统

本身已经提供了一些内容提供者,它们允许我们查询联系人,媒体库,和短息消息等。

 

基于Content Uri的查询:

      没有Uri,ContentProvider 类基本无法工作,就像我们上网没有网址。当我们要上网,就要在地址栏输入网址。

 

因此,要了解ContentProvider,我们必须先了解 Content Uri

下面是Uri的基本格式:

content://authority/optionalPath/optionalId

 

content://是内容提供者的标准前缀,而且它必须是content://。authority由我们自己定义,它必须具有唯一性,

因此我们一般使用应用程序包名命名authority。optionalPath和optionalId是可选的。

 

下面我们来看一下WordPress的文章地址格式:

http://www.whathecode.com/archives/221

 

http:// 是http协议的标准写法,它是规定的,没有为什么。

www.whathecode.com可以理解为authority,因为域名是唯一的,它可以分辨我们要访问哪一个网站。

arichives可以理解为文章的分类。

最后的221就是文章的id,假如我们要查看第一遍文章,只要将221改成1就可以。

这样理解Uri是不是简单了很多。

 

建立自己的ContentProvider

建立ContentProvider只需几部:

1. 设计数据库的储存方式,因为ContentProvider提供的是数据,没有数据,ContentProvider就没有了用处。

2. 定义自己的类,继承ContentProvider类,并实现基本的方法。

3. 设计authority字符串。(要被人访问你的网站,你就需要一个网址,当然ip地址也可以)

4. 在AndroidManifest中注册Provider

 

我们先来研究一下代码:

作为示例下面的代码只实现了query方法,而且只添加了一个Uri,

一般应用程序都不只一个Uri

package com.whathecode.provider;



import android.content.ContentProvider;

import android.content.ContentValues;

import android.content.Context;

import android.content.Intent;

import android.content.UriMatcher;

import android.database.Cursor;

import android.database.sqlite.SQLiteDatabase;

import android.database.sqlite.SQLiteDatabase.CursorFactory;

import android.database.sqlite.SQLiteOpenHelper;

import android.net.Uri;

import android.util.Log;

import android.widget.Toast;



public class MemberProvider extends ContentProvider

{

	

	private static final UriMatcher sMatcher;

	private static final String MEMBER_NAME = "name";

	private static final int QUERY_BY_NAME = 0;

	private static final String DB_NAME = "member.db";

	private static final String TAG = "MemberProvider";



	

	static

	{

		sMatcher = new UriMatcher(UriMatcher.NO_MATCH);

		/**

		 * 添加需要匹配的Uri, 当这个Uri被匹配的时候返回第三个参数。

		 * 得到这个参数之后就可以在query,insert,update,delete

		 * 方法中做出相应的动作。

		 */

		sMatcher.addURI(Member.AUTHORITY, MEMBER_NAME, QUERY_BY_NAME);

	}

	

	private static class DataBaseHelper extends SQLiteOpenHelper

	{



		public DataBaseHelper(Context context, String name,

				CursorFactory factory, int version)

		{

			super(context, name, factory, version);

		}



		@Override

		public void onCreate(SQLiteDatabase db)

		{

			//建立数据库表结构

			db.execSQL("create table member(_id integer primary key," +

					"name varchar(20)," +

					"work varchar(20)," +

					"age integer)");

		}



		@Override

		public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)

		{

			// TODO Auto-generated method stub



		}



	}



	private DataBaseHelper mHelper;



	@Override

	public boolean onCreate()

	{

		mHelper = new DataBaseHelper(getContext(), DB_NAME, null, 2);

		return true;

	}



	@Override

	public Cursor query(Uri uri, String[] projection, String selection,

			String[] selectionArgs, String sortOrder)

	{



		 /**

		  * 前面我们在静态代码块中已添加了Uri库

		  * 当每个Uri作为参数传进来的时候我们都先进行匹配

		  * 

		  */

		switch (sMatcher.match(uri)) 

		{

		case QUERY_BY_NAME:

			//第一次执行时生成数据库member.db

			SQLiteDatabase readableDatabase = mHelper.getReadableDatabase();

			/**

			 * 当query方法执行的时候向外发送广播

			 */

			Intent intent = new Intent();

			intent.setAction("com.contentprovider.execquery");

			intent.putExtra("MemberProvider", "query方法执行了");

			getContext().sendBroadcast(intent);

			break;



		default:

			/**

			 * 当Uri匹配失败的时候说明Uri参数错误,无法继续进行操作,

			 * 因此程序抛出一个错误

			 */

			throw new IllegalArgumentException("Unknown URI " + uri);

		}

		return null;

	}

	

	@Override

	public String getType(Uri uri)

	{

		// TODO Auto-generated method stub

		return null;

	}



	@Override

	public Uri insert(Uri uri, ContentValues values)

	{

		// TODO Auto-generated method stub

		return null;

	}



	@Override

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

	{

		// TODO Auto-generated method stub

		return 0;

	}



	@Override

	public int update(Uri uri, ContentValues values, String selection,

			String[] selectionArgs)

	{

		// TODO Auto-generated method stub

		return 0;

	}



}

这样,一个虽简单但可行的内容提供者就创建好了,现在我们只需在AndroidManifest文件中注册它。

<provider android:name="com.whathecode.provider.MemberProvider"

      android:authorities="com.whathecode.contentproviderdemo.member">

</provider>

 

接下来,运行这个程序,将我们刚才定义的ContentProvider部署到模拟器。

然后,我们建立另外一个程序测试这个内容提供者是否真的工作正常。

 

下面是另外一个程序的代码:

我们需要另外一个类进行访问ContentProvider提供的数据。

这个类就是ContentResolver,它提供了和ContentProvider一样的CRUD方法。

方便我们查询数据。

package com.whathecode.contentprovidertest;



import android.app.Activity;

import android.content.BroadcastReceiver;

import android.content.ContentResolver;

import android.content.Context;

import android.content.Intent;

import android.content.IntentFilter;

import android.net.Uri;

import android.os.Bundle;

import android.view.View;

import android.widget.Toast;



public class MainActivity extends Activity

{



	private BroadcastReceiver receiver;

	@Override

	protected void onCreate(Bundle savedInstanceState)

	{

		super.onCreate(savedInstanceState);

		setContentView(R.layout.activity_main);

		



		//创建一个广播接受者用于接收MemberProvider发出的广播

		receiver = new BroadcastReceiver()

		{



			@Override

			public void onReceive(Context context, Intent intent)

			{

				/**

				 * 当广播被接收到的时候Toast提示用户接收到的信息

				 */

				Toast.makeText(getBaseContext(),

						"收到的信息" + intent.getStringExtra("MemberProvider"),

						Toast.LENGTH_SHORT).show();

			}

		};

	}

	

	@Override

	protected void onResume()

	{

		super.onResume();

		//注册广播接受者

		registerReceiver(receiver, new IntentFilter("com.contentprovider.execquery"));

	}



	public void onClick(View view)

	{

		/**

		 * 获取ContentResolver实例访问ContentProvider

		 */

		ContentResolver resolver = getContentResolver();

		Uri uri = Uri

				.parse("content://com.whathecode.contentproviderdemo.member/name");

		resolver.query(uri, null, null, null, null);

	}

	

	@Override

	protected void onPause()

	{

		super.onPause();

		//取消注册广播接受者

		unregisterReceiver(receiver);

	}

}

 

运行效果:

如果Toast运行证明MemberProvider中的query方法被成功执行

ContentProvider

你可能感兴趣的:(ContentProvider)