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

来源:互联网 发布:mac 安装adobe字体 编辑:程序博客网 时间:2024/04/28 11:42

在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 {//外部发访问Authroitypublic 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);}@Overridepublic 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{//实例化UriMatcheruriMatcher = new UriMatcher(UriMatcher.NO_MATCH);//增加匹配URIuriMatcher.addURI(DatabaseMetaData.AUTHROITY, "member", GET_MEMBER_LIST);uriMatcher.addURI(DatabaseMetaData.AUTHROITY, "member/#", GET_MEMBER_ITEM);}@Overridepublic boolean onCreate() {this.helper = new MyDatabaseHelper(super.getContext());return true;}@Overridepublic 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);}}@Overridepublic 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);//抛出异常}}@Overridepublic 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);}}@Overridepublic int delete(Uri uri, String selection, String[] selectionArgs) {// TODO Auto-generated method stubreturn 0;}@Overridepublic int update(Uri uri, ContentValues values, String selection,String[] selectionArgs) {// TODO Auto-generated method stubreturn 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();//获取ContentResolverContentValues 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



0 0