Android中5大数据存储(四)---ContentProvider

在Android中,每一个应用程序的数据都是采取私有的形式进行操作,不管这些数据是用文件还是数据库保存,都不能被外部应用程序所访问。但是咋很多情况下,用户需要可以在不同的应用程序之间进行交换的数据,所以为了解决这个问题,在Android中专门提供了一个ContentProvider类,此类的主要功能是将不同的应用程序的数据操作标准统一起来,并且将各个应用程序的数据操作标准表明给其他应用程序,这样,一个应用程序的数据就可以按照ContentProvider所定制的标准被外部所操作。

ContentProvider在程序操作中所提供的是一个操作标准,所以如果要想依靠此标准进行数据操作,必须使用ContentResolver类来完成,而该类中所给出的操作方法与ContentProvider是一一对应的,当用户调用ContentResolver类的方法是,实际上就是相当于用了ContentProvider类中的方法。具体操作关系如下图:

                       

注:关于ContentProvider/ContentResolver的理解:前者提供了对SQLite的一些操作的标准化封装,如同为SQLite制作好了一把锁,后者就是开这把锁的药匙,以后程序中任何有关SQLite的操作,都必须先实例化ContentResolver对象,取得ContentResolver,再使用UriMatcher匹配成功uri,之后就可以进行有关的insert、delete、update等操作。


由于这次涉及的代码量有点多,下面就逐个讲解重点部分,首先声明一个DatabaseMateData借口类,里面封装了有关操作的元数据,有外部访问链接,数据库名称,数据库版本,数据表名称,数据库字段等,具体java文件如下:

package cn.norysn.contentproviderdemo;

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

public interface DatabaseMetaData {
	//外部发访问Authroity
	public static final String AUTHROITY = "cn.norysn.membercontentprovider";
	//public static final String AUTHROITY = "cn.norysn.contentproviderdemo";
	//定义数据库名称
	public static final String DATABASE_NAME = "norysn.db";
	//数据库版本
	public static int VERSION = 1;
	//member表的元数据定义
	public static interface MemberTableMetaData extends BaseColumns{
		//数据表名称
		public static final String TABLE_NAME = "member";
		//外部访问URI地址
		public static final Uri CONTENT_URI = Uri.parse("content://"
				+AUTHROITY+"/"+TABLE_NAME);
		//取得memeber表中的所有数据
		public static final String CONTENT_LIST = "vnd.android.cursor.dir/vnd.contentproviderdemo.member";
		//按ID查询
		public static final String CONTENT_ITEM = "vnd.android.cursor.item/vnd.contentproviderdemo.member";
		//member字段名称
		public static final String MEMBER_NAME = "name";
		public static final String MEMBER_AGE = "age";
		public static final String MEMBER_BIRTHDAY = "birthday";
		public static final String SORT_ORDER = "_id DESC";
	}
}

定义了数据库操作的助手类,MyDatabaseHelper.java,这个类的功能与之前章节中介绍的一样,主要是用来创建数据库,数据表,源码如下:

package cn.norysn.contentproviderdemo;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class MyDatabaseHelper extends SQLiteOpenHelper {

	//数据库名称
	private static final String DATABASE_NAEM = "norysn.db";
	//版本号
	private static final int DATABASE_VERSION = 1;
	//数据表名称
	private static final String TABLE_NAME = "member";
	public MyDatabaseHelper(Context context) {
		//构造父类
		super(context, DATABASE_NAEM, null, DATABASE_VERSION);
	}

	@Override
	public void onCreate(SQLiteDatabase db) {
		//sql语句
		String sql = "create table "+TABLE_NAME+" ("
		+DatabaseMetaData.MemberTableMetaData._ID
		+" integer primary key ,"
		+DatabaseMetaData.MemberTableMetaData.MEMBER_NAME
		+" varchar(20) not null ,"
		+DatabaseMetaData.MemberTableMetaData.MEMBER_AGE
		+" integer not null ,"
		+DatabaseMetaData.MemberTableMetaData.MEMBER_BIRTHDAY
		+" date not null)";
		//执行SQL语句
		db.execSQL(sql);
	}
	
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
		String sql = "drop table if exists "+TABLE_NAME;
		db.execSQL(sql);
		this.onCreate(db);
	}
}

接着定义member表操作的MemberContentProvider类,该类必须继承ContentProvider类,并且在类中覆写抽象方法,本例子中只是在oncreate(),insert(),query()中做了相应的代码添加,代码如下:

package cn.norysn.contentproviderdemo;

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;

public class MemberContentProvider extends ContentProvider {
	//定义UriMatcher对象
	private static UriMatcher uriMatcher = null;
	//定义常量标记
	private static final int GET_MEMBER_LIST = 1;
	private static final int GET_MEMBER_ITEM = 2;
	private MyDatabaseHelper helper = null;
	static{
		//实例化UriMatcher
		uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
		//增加匹配URI
		uriMatcher.addURI(DatabaseMetaData.AUTHROITY, "member", GET_MEMBER_LIST);
		uriMatcher.addURI(DatabaseMetaData.AUTHROITY, "member/#", GET_MEMBER_ITEM);
	}

	@Override
	public boolean onCreate() {
		this.helper = new MyDatabaseHelper(super.getContext());
		return true;
	}

	@Override
	public Cursor query(Uri uri, String[] projection, String selection,
			String[] selectionArgs, String sortOrder) {
		//SQLiteDatabase db = this.helper.getWritableDatabase();
		SQLiteDatabase db = this.helper.getReadableDatabase();
		switch(uriMatcher.match(uri)){
		case GET_MEMBER_LIST:
			//查询操作
			return db.query(DatabaseMetaData.MemberTableMetaData.TABLE_NAME,
					projection, selection, selectionArgs, null, null, sortOrder);
		case GET_MEMBER_ITEM:
			long id = ContentUris.parseId(uri);
			String where = "_id="+id;
			return db.query(DatabaseMetaData.MemberTableMetaData.TABLE_NAME, 
					projection, where, selectionArgs, null, null, sortOrder);
		default:
			//抛出异常
			throw new UnsupportedOperationException("Not Support query Operation:"+uri);
		
		}
	}

	@Override
	public String getType(Uri uri) {
		//match()指定URI位置
		switch(uriMatcher.match(uri)){
		case GET_MEMBER_LIST:
			return DatabaseMetaData.MemberTableMetaData.CONTENT_LIST;
		case GET_MEMBER_ITEM:
			return DatabaseMetaData.MemberTableMetaData.CONTENT_ITEM;
		default:
			throw new UnsupportedOperationException("Not Support Operation: "+uri);//抛出异常
		}
	}

	@Override
	public Uri insert(Uri uri, ContentValues values) {
		SQLiteDatabase db = helper.getWritableDatabase();//取得数据库对象
		long id = 0;
		switch(uriMatcher.match(uri)){
		case GET_MEMBER_LIST:
			id = db.insert(DatabaseMetaData.MemberTableMetaData.TABLE_NAME,
					DatabaseMetaData.MemberTableMetaData._ID, values);
			return ContentUris.withAppendedId(uri, id);
		case GET_MEMBER_ITEM:
			id = db.insert(DatabaseMetaData.MemberTableMetaData.TABLE_NAME,
					DatabaseMetaData.MemberTableMetaData._ID, values);
			String uriPath = uri.toString();
			String path = uriPath.substring(0,uriPath.lastIndexOf("/"))+id;
			return Uri.parse(path);
		default:
			throw new UnsupportedOperationException("Not Support insert Opetarion:"+uri);
		}
	}

	@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;
	}

}

最后就是主Activity(MyContentProviderDemo)操作了,当按下增加按钮时,完成数据库、数据表的创建,并使用Toast提示,当按下查询按钮之后,使用ListView控件,自定义布局member.xml文件显示查询结果。

package cn.norysn.contentproviderdemo;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;
import android.widget.Toast;

public class ContentProviderDemo extends Activity {

	//定义组件
	private Button insertBtn = null;
	private Button queryBtn = null;
	private TextView showInfo = null;
	private ListView membersList = null;
	
	public long testInsert(String name, int age, String birthday) throws Exception{
		ContentResolver contentResolver = null;
		contentResolver  = getContentResolver();//获取ContentResolver
		ContentValues values = new ContentValues();//设置内容
		values.put(DatabaseMetaData.MemberTableMetaData.MEMBER_NAME, name);
		values.put(DatabaseMetaData.MemberTableMetaData.MEMBER_AGE, age);
		values.put(DatabaseMetaData.MemberTableMetaData.MEMBER_BIRTHDAY, birthday);
		//执行增加操作
		Uri resultUri = contentResolver.insert(DatabaseMetaData.MemberTableMetaData.CONTENT_URI, values);
		
		return ContentUris.parseId(resultUri);
		
	}
	public Cursor testQuery(String id) throws Exception{
		//查询全部
		if(id==null || "".equals(id)){
			return super.getContentResolver().query(DatabaseMetaData.MemberTableMetaData.CONTENT_URI,
					null,null, null, DatabaseMetaData.MemberTableMetaData.SORT_ORDER);
		}else{
			//根据ID查询
			return super.getContentResolver().query(Uri.withAppendedPath(DatabaseMetaData.MemberTableMetaData.CONTENT_URI,id),
					null, null, null, DatabaseMetaData.MemberTableMetaData.SORT_ORDER);
		}
	}
	
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        //获得组件ID
        insertBtn = (Button)findViewById(R.id.insertBtn);
        queryBtn = (Button)findViewById(R.id.queryBtn);
        showInfo = (TextView)findViewById(R.id.showinfo);
        membersList = (ListView)findViewById(R.id.membersList);
        //设置监听事件
        insertBtn.setOnClickListener(new insertBtnListener());
        queryBtn.setOnClickListener(new queryBtnListener());
    }
    public class insertBtnListener implements OnClickListener{
		public void onClick(View v) {
			showInfo.setText("执行的是增加操作...");
		long id = 0;
		try {
			id = ContentProviderDemo.this.testInsert("luhua", 26,
					new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
		} catch (Exception e) {
			e.printStackTrace();
		}
		Toast.makeText(ContentProviderDemo.this, "数据增加成功,ID为:"+id, Toast.LENGTH_LONG).show();
		}
    }
    //query operate
    public class queryBtnListener implements OnClickListener{
		@SuppressWarnings("deprecation")
		public void onClick(View v) {
			showInfo.setText("执行的是查询操作...");
			Cursor result = null;
			try {
				result = ContentProviderDemo.this.testQuery(null);
			} catch (Exception e) {
				e.printStackTrace();
			}
			//System.out.println(result.getInt(0));
			if(result != null){
				System.out.println("result is not null");
			}else{
				System.out.println("result is null");
			}
			//Cursor交由系统管理
			ContentProviderDemo.this.startManagingCursor(result);
			List<Map<String, Object>> members = null;
			members = new ArrayList<Map<String, Object>>();
			for(result.moveToFirst();!result.isAfterLast();result.moveToNext()){
				Map<String, Object> member = new HashMap<String, Object>();
				member.put("_id", result.getInt(0));
				member.put("name", result.getString(1));
				member.put("age", result.getInt(2));
				member.put("birthday", result.getString(3));
				members.add(member);//保存Map中
			}
			//ContentProviderDemo.this.stopManagingCursor(result);
			//适配器
			ContentProviderDemo.this.membersList.setAdapter(new SimpleAdapter(ContentProviderDemo.this,
					members, 
					R.layout.member,
					new String[]{"_id", "name", "age", "birthday"},
					new int[]{R.id._id, R.id.name, R.id.age, R.id.birthday}));//显示数据
		Toast.makeText(ContentProviderDemo.this, "数据查询成功,ID为:", Toast.LENGTH_LONG).show();
		}
    }
}

修改AndroidManifest.xml文件,配置ContentProvider权限:

<provider
            android:name=".MemberContentProvider"
            android:authorities="cn.norysn.membercontentprovider"></provider>

android:authorities属性与DatabaseMetaData接口中配置的AUTHORITY全局常量一致,以后访问此ContentProvider程序的Uri的组成部分。


查询效果截图:


 源码下载      密码:j3fe



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值