Android ContentProvider学习

ContentProvider介绍:

Android ContentProvider是数据对外的接口,我们只需通过使用ContentProvider访问数据而不需要关心数据具体的存储及访问过程,这样既提高了数据的访问效率,同时也保护了数据。Activity类中有一个继承自ContentWapper的getContentResolver()无参数方法,该方法返回一个ContentResolver对象,通过调用其query、insert、update、delete方法访问数据。这几个方法的第一个参数均为URI型,用来标识资源。

总结:
1、ContentProvider为存储和读取数据提供了统一的接口
2、使用ContentProvider,应用程序可以实现数据共享
3、android内置的许多数据都是使用ContentProvider形式,供开发者调用的(如视频,音频,图片,通讯录等)

Uri介绍:

1、每一个ContentProvider都拥有一个公共的Uri,这个Uri用于表示这个ContentProvider提供的数据
2、Android所提供的ContentProvider都存放在andriod.provider这个包里面

Android的ContentProvider URI有固定的形式:content://contract/people

前缀:固定为content : //
认证:contract 资源的唯一标识符
路径:people 具体的资源类型

在Android中广泛应用URI,而不是URL。URL标识资源的物理位置,相当于文件的路径;而URI则是标识资源的逻辑位置,并不提供资源的具体位置。比如说电话薄中的数据,如果用URL来标识的话,可能会是一个很复杂的文件结构,而且一旦文件的存储路径改变,URL也必须得改动。但是若是URI,则可以用诸如content://contract/people这样容易记录的逻辑地址来标识,而且并不需要关心文件的具体位置,即使文件位置改动也不需要做变化,当然这都是对于用户来说,后台程序中URI到具体位置的映射还是需要程序员来改动的。

ContentProvider提供的函数:

1、query() 查询
2、insert() 插入
3、update() 更新
4、delete() 删除
5、getType() 得到数据类型
6、onCreate() 创建时的回调函数

实现ContentProvider的过程:

1、定义一个COTENT_URI常量
2、定义一个类,继承ContentProvider
3、实现query(),delete(),update(),insert(),onCreate(),getType()方法
4、在AndroidMainfest.xml中申明

下面以两个实例(一个是ContentProvider所在的应用,另一个是使用ContentProvider的应用),说明如何使用ContentProvider

ContentProvider所在的应用

1、定义一个类,里面定义一些常量

package com.yyl.android;

import android.net.Uri;
import android.provider.BaseColumns;

public class MyUsers {

	public static final String AUTHORITY = "com.yyl.android.MyContentProvider";

	// BaseColumn类中已经包含了_id字段
	public static final class User implements BaseColumns {
		// 定义Uri
		public static final Uri CONTENT_URI = Uri.parse("content://"
				+ AUTHORITY);
		// 定义数据表列
		public static final String USER_NAME = "USER_NAME";
	}

}

2、定义一个继承ContentProvider的子类,实现其方法

package com.yyl.android;

import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;

/**
 * MyContentProvider继承ContentProvider类,实现其insert,update,delete,getType,onCreate等方法
 */
public class MyContentProvider extends ContentProvider {

	// 定义一个SQLiteDatabase变量
	private SQLiteDatabase sqlDB;
	// 定义一个DatabaseHelper变量
	private DatabaseHelper dbHelper;
	// 数据库名
	private static final String DATABASE_NAME = "Users.db";
	// 数据库版本
	private static final int DATABASE_VERSION = 1;
	// 表名
	private static final String TABLE_NAME = "User";
	// 标签
	private static final String TAG = "MyContentProvider";

	/**
	 * 定义一个内部类
	 * 
	 * 这个内部类继承SQLiteOpenHelper类,重写其方法
	 */
	public static class DatabaseHelper extends SQLiteOpenHelper {

		// 构造方法
		public DatabaseHelper(Context context) {
			// 父类构造方法
			super(context, DATABASE_NAME, null, DATABASE_VERSION);
		}

		// 当第一次创建数据库的时候调用该方法,可以为数据库增加一些表,和初始化一些数据
		@Override
		public void onCreate(SQLiteDatabase db) {
			// 在数据库里生成一张表
			db.execSQL("Create table "
					+ TABLE_NAME
					+ "( _id INTEGER PRIMARY KEY AUTOINCREMENT, USER_NAME TEXT);");
		}

		// 当更新数据库版本的时候,调用该方法。可以删除,修改表的一些信息
		@Override
		public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
			db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
			onCreate(db);

		}

	}

	// 这是一个回调函数,当生成所在类的对象时,这个方法被调用,创建一个数据库
	@Override
	public boolean onCreate() {
		dbHelper = new DatabaseHelper(getContext());
		return (dbHelper == null) ? false : true;
	}

	// 查询
	@Override
	public Cursor query(Uri uri, String[] projection, String selection,
			String[] selectionArgs, String sortOrder) {
		SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
		SQLiteDatabase db = dbHelper.getReadableDatabase();
		qb.setTables(TABLE_NAME);
		Cursor c = qb.query(db, projection, selection, null, null, null,
				sortOrder);
		c.setNotificationUri(getContext().getContentResolver(), uri);
		return c;
	}

	// 取得类型
	@Override
	public String getType(Uri uri) {
		return null;
	}

	// 插入数据
	@Override
	public Uri insert(Uri uri, ContentValues contentvalues) {
		sqlDB = dbHelper.getWritableDatabase();
		long rowId = sqlDB.insert(TABLE_NAME, "", contentvalues);
		if (rowId > 0) {
			Uri rowUri = ContentUris.appendId(
					MyUsers.User.CONTENT_URI.buildUpon(), rowId).build();
			getContext().getContentResolver().notifyChange(rowUri, null);
			return rowUri;
		}
		throw new SQLException("Failed to insert row into" + uri);
	}

	// 删除数据
	@Override
	public int delete(Uri uri, String selection, String[] selectionArgs) {
		return 0;
	}

	// 更新数据
	@Override
	public int update(Uri uri, ContentValues values, String selection,
			String[] selectionArgs) {
		return 0;
	}

}

3、定义一个默认加载的Activity,里面对ContentProvider进行数据加载

package com.yyl;

import com.yyl.android.MyUsers;
import android.app.Activity;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.widget.Toast;

public class MyContentDemo extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		insertRecord("MyUser");
		insertRecord("YangYuLin");
		displayRecords();
	}

	private void insertRecord(String userName) {
		ContentValues values = new ContentValues();
		values.put(MyUsers.User.USER_NAME, userName);
		getContentResolver().insert(MyUsers.User.CONTENT_URI, values);
	}

	private void displayRecords() {
		String columns[] = new String[] { MyUsers.User._ID,
				MyUsers.User.USER_NAME };
		Uri myUri = MyUsers.User.CONTENT_URI;
		Cursor cur = managedQuery(myUri, columns, null, null, null);
		if (cur.moveToFirst()) {
			String id = null;
			String userName = null;
			do {
				id = cur.getString(cur.getColumnIndex(MyUsers.User._ID));
				userName = cur.getString(cur
						.getColumnIndex(MyUsers.User.USER_NAME));
				Toast.makeText(this, id + " " + userName, Toast.LENGTH_LONG)
						.show();
			} while (cur.moveToNext());
		}
	}
}

4、在AndroidMainfest.xml里注册

做另一个App.使用上面ContentProvider提供的数据

package yyl.client;

import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.text.Editable;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

public class CPClientActitity extends Activity {

	public static final String AUTHORITY = "com.yyl.android.MyContentProvider";
	private Button insertButton = null;
	// 访问ContentProvider的Uri
	Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY);

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		// 得到ContentProvider对于表的所有数据,以游标格式保存
		Cursor c = managedQuery(CONTENT_URI,
				new String[] { "_id", "USER_NAME" }, null, null, null);

		// 循环打印ContentProvider的数据
		if (c.moveToFirst()) {
			String _id = null;
			String user_name = null;

			do {
				// 得到_id列,USER_NAME列
				_id = c.getString(c.getColumnIndex("_id"));
				user_name = c.getString(c.getColumnIndex("USER_NAME"));

				System.out.println("_id = " + _id + ", user_name = "
						+ user_name);

			} while (c.moveToNext());
		}

		// 根据Id得到控件对象
		insertButton = (Button) findViewById(R.id.Insert);
		// 给按钮绑定事件监听器
		insertButton.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {

				// 得到EditText输入的数据
				String username = ((EditText) findViewById(R.id.userName))
						.getText().toString();
				// 生成一个ContentResolver对象
				ContentResolver cr = getContentResolver();
				// 生成一个ContentValues对象
				ContentValues values = new ContentValues();
				// 将EditText输入的值,保存到ContentValues对象中
				values.put("USER_NAME", username);
				// 插入数据
				cr.insert(CONTENT_URI, values);
			}
		});
	}
}
暂无评论
  • 1:请一针见血的评论。
  • 2:评论需要审核通过后才能显示。
  • 3:评论字数限制在1000字以内。
  • 当前字数:0
热门文章
推荐文章
随机文章
关于本站 - 广告服务 - 版权声明 - 联系我们 - 友情链接 - 网站地图 - 帮助中心