Android学习十九:ContentProvider初步

本文详细介绍了Android中的ContentProvider组件,包括其基本概念、URI使用方法、实现过程及具体代码示例。帮助开发者理解如何在不同应用间共享数据。

转新浪 生活啊,我爱你! 博客:http://blog.sina.com.cn/s/blog_5688414b0100xagp.html


一、ContentProvider基本概念 

1ContentProvider为存储和获取数据提供了统一的接口。ContentProvide对数据进行封装,不用关心数据存储的细节。使用表的形式来组织数据。

Android学习十九:ContentProvider初步

2、使用ContentProvider可以在不同的应用程序之间共享数据。 

3Android为常见的一些数据提供了默认的ContentProvider包括音频、视频、图片和通讯录等  

ContentProvider所提供的函数

query(),insert(),update(),delete(),getType(),onCreate()等。

 二、URI统一资源标识符)的使用方法

为系统的每一个资源给其一个名字,比方说通话记录。

1、每一个ContentProvider都拥有一个公共的URI这个URI用于表示这个ContentProvider所提供的数据。 

2Android所提供的ContentProvider都存放在android.provider包中。 将其分为ABCD4个部分:

Android学习十九:ContentProvider初步

A:标准前缀,用来说明一个Content Provider控制这些数据,无法改变的;"content://"

 BURI的标识,它定义了是哪个ContentProvider提供这些数据。对于第三方应用程序,为了保证URI标识的唯一性,它必须是一个完整的、小写的 类名。这个标识在 元素的 authorities属性中说明:一般是定义该ContentProvider的包.类的名称;"content://hx.android.text.myprovider"

C:路径,不知道是不是路径,通俗的讲就是你要操作的数据库中表的名字,或者你也可以自己定义,记得在使用的时候保持一致就ok了;"content://hx.android.text.myprovider/tablename"

D:如果URI中包含表示需要获取的记录的ID;则就返回该id对应的数据,如果没有ID,就表示返回全部; "content://hx.android.text.myprovider/tablename/#"#表示数据id

三、ContentProvider的实现过程

自己实现ContentProvider不常见因为可能不需要和别的应用程序交换数据。使用内置的ContentProvider比较多 

   1、定义一个CONTENT_URI常量,提供了访问ContentProvider的标识符。 

public static final Uri CONTENT_URI = Uri.parse("content://com.example.codelab.transportationprovider");

其中:content是协议

     Com.exmaple.codelab.transportationprovider是类名,包含完整的包名。

Uri.parse将一个字符串转换成Uri类型。

如果Provider包含子表,同样定义包含字表的CONTENT_URI

content://com.example.codelab.transportationprovider/train 
content://com.example.codelab.transportationprovider/air/domestic 
content://com.example.codelab.transportationprovider/air/international

然后定义列,确保里面包含一个_id的列。

   2、定义一个类继承ContentProvider 

publicclass FirstContentProvider extends ContentProvider

先介绍一下ContentProvider用到的UriMatcherUriMatcher的一个重要的函数是match(Uri uri)。这个函数可以匹配Uri,根据传入的不同Uri返回不同的自定义整形值,以表明Uri访问的不同资源的类型。

     例如

      public static final UriMatcher uriMatcher;  
      static {  
                     uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);  
                     uriMatcher.addURI(Book.AUTHORITY, "item", Book.ITEM);  
                     uriMatcher.addURI(Book.AUTHORITY, "item/#", Book.ITEM_ID);  
              } 

     这里UriMatcher类型的静态字段是用来匹配传入到ContentProvider中的Uri的类。其构造方法传入的匹配码是使用match()方法匹配根路径时返回的值,这个匹配码可以为一个大于零的数表示匹配根路径或传入-1,即常量UriMatcher.NO_MATCH表示不匹配根路径。 addURI()方法是用来增加其他URI匹配路径的,第一个参数传入标识ContentProviderAUTHORITY字符串。第二个参数传入需要匹配的路径,这里的#号为通配符,代表匹配任意数字,另外还可以用*来匹配任意文本。第三个参数必须传入一个大于零的匹配码,用于match()方法对相匹配的URI返回相对应的匹配码。 例如:sMatcher.addURI(com.test.provider.personprovider,person,1);如果match()方法匹配content://com.test.provider.personprovider/person路径,返回匹配码为1

   3、实现query,insert,update,delete,getTypeonCreate方法。 

   4、在AndroidManifest.xml当中进行声明。

<!-- android:name是完成ContentProvider类的全称
             android:authorities是和FirstProvidermetaData中的常量AUTHORITY的值一样否则会报错
         -->
        <provider android:name="com.bj.FirstContentProvider"
            android:authorities="com.bj.firstcontentprovider"
            />

 

 

四、具体代码

Activity19Activity.java

public class Activity19Activityextends Activity {

   

   private Button queryButton = null;

   private Button insertButton = null;

 

   @Override

   public void onCreate(Bundle savedInstanceState){

      super.onCreate(savedInstanceState);

      setContentView(R.layout.main);

      queryButton = (Button) this.findViewById(R.id.query);

      queryButton.setOnClickListener(newQueryListener());

      insertButton = (Button) this.findViewById(R.id.insert);

      insertButton.setOnClickListener(newInsertListener());

       System.out.println(getContentResolver().getType(FirstProvidermetaData.UserTableMetaData.CONTENT_URI));

   }

 

   class InsertListener implementsOnClickListener {

 

      @Override

      public void onClick(View v) {

          // TODOAuto-generated method stub

          ContentValues values = new ContentValues();

          values.put(FirstProvidermetaData.UserTableMetaData.USER_NAME,

                 "michal");

          Uri uri = getContentResolver()

                 .insert(

                        FirstProvidermetaData.UserTableMetaData.CONTENT_URI,

                        values);

          System.out.println("uri--->"+ uri.toString());

      }

 

   }

 

   class QueryListener implementsOnClickListener {

      public void onClick(View v) {

          Cursor c =getContentResolver().query(

                 FirstProvidermetaData.UserTableMetaData.CONTENT_URI, null,

                 null, null, null);

          while (c.moveToNext()) {

             System.out.println(c.getString(c.getColumnIndex("username")));

 

          }

 

      }

   }

}

FirstContentProvider.java

public class FirstContentProviderextendsContentProvider {

   // 当别的程序来访问这个ContentProvider,是通过Uri来访问的,UriMatcher检查是否符合标准

   // uri起一个规则,返回数字

   public static final UriMatcher uriMatcher;

   // 下面定义两个规则

   public static final int INCOMING_USER_COLLECTION= 1;

   public static final int INCOMING_USER_SINGLE= 2;

   private DatabaseHelper dh;

   static {//下面的users前面不能加/

      uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);

      uriMatcher.addURI(FirstProvidermetaData.AUTHORITY, "users",

             INCOMING_USER_COLLECTION);

      uriMatcher.addURI(FirstProvidermetaData.AUTHORITY, "users/#",

             INCOMING_USER_SINGLE);

   }

   

   //有点类似于sql里面表的别名,这个也是给列其别名,必须要用

   //列的别名还是原来的名,没必要修改

   public static HashMap<String,String>userProjectionMap;

   static{

      userProjectionMap= newHashMap<String,String>();

      userProjectionMap.put(UserTableMetaData._ID,UserTableMetaData._ID );

      userProjectionMap.put(UserTableMetaData.USER_NAME,UserTableMetaData.USER_NAME);

   }

 

   @Override

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

      // TODOAuto-generated method stub

      System.out.println("delete");

      return 0;

   }

 

   // 根据传入的URI,返回该URI所表示的数据类型

   // 也就是说,我们通过URI要访问的数据,返回什么类型

   @Override

   public String getType(Uri uri) {

      // TODOAuto-generated method stub

      System.out.println("getType");

      switch (uriMatcher.match(uri)) {

      case INCOMING_USER_COLLECTION:

          //UserTableMetaDataFirstProvidermetaData的内部类

          return UserTableMetaData.CONTENT_TYPE;

      case INCOMING_USER_SINGLE:

          return UserTableMetaData.CONTENT_TYPE_ITEM;

      default:

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

      }

   }

 

   

   @Override

   public Uri insert(Uri uri, ContentValuesvalues) {

      // TODOAuto-generated method stub

      System.out.println("insert");

      SQLiteDatabase db = dh.getWritableDatabase();

      //返回表中自动增长的列的值,否则返回-1     

      long rowId =db.insert(UserTableMetaData.TABLE_NAME,null, values);   

      if(rowId>0){

          //rowId追加到后面

          //contentUris:用来处理Uri的工具类

          Uri insertedUserUri =ContentUris.withAppendedId(UserTableMetaData.CONTENT_URI, rowId);

          //通知监听器,数据已经改变

          getContext().getContentResolver().notifyChange(insertedUserUri,null);

          return insertedUserUri;

      }

      throw new SQLException("Failed to insert row into"+uri);

   }

   

   //是一个回调方法,所以说在ContentProvider创建的时候执行

   //也就是创建这个DatabaseHelper对象

   @Override

   public boolean onCreate() {

      // TODOAuto-generated method stub

      //getContext得到当前正在运行着的context

      dh = new DatabaseHelper(getContext(),FirstProvidermetaData.DATABASE_NAME);

      System.out.println("on create");

      SQLiteDatabase db = dh.getReadableDatabase();

      return true;

   }

   

   //projection:查询的列有哪些

   //selection:where子句的内容,可以用?

   //selectionArgs:占位符对应的参数

   //sortOrder:排序

   @Override

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

          String[] selectionArgs, String sortOrder) {

      // TODOAuto-generated method stub

      System.out.println("query");

      //创建一个查询的语句

      SQLiteQueryBuilder qb = new SQLiteQueryBuilder();

      switch(uriMatcher.match(uri)){

      case INCOMING_USER_COLLECTION:

          //设置查询哪张表

          qb.setTables(UserTableMetaData.TABLE_NAME);

          qb.setProjectionMap(userProjectionMap);

          break;

      case INCOMING_USER_SINGLE:

          qb.setTables(UserTableMetaData.TABLE_NAME);

          qb.setProjectionMap(userProjectionMap);

          //添加where条件,getPathSegments:得到uripath部分content:XXX/user/1get(1)得到1

          qb.appendWhere(UserTableMetaData._ID+"="+uri.getPathSegments().get(1));

          break;

      }

      

      String orderBy;

      if(TextUtils.isEmpty(sortOrder)){

          orderBy = UserTableMetaData.DEFAULT_SORT_ORDER;

      }

      else

      {

          orderBy = sortOrder;

      }

      SQLiteDatabase db = dh.getWritableDatabase();

      //下面的query使用qb这个对象

      Cursor c = qb.query(db, projection, selection,selectionArgs, null, null, orderBy);

      //也是通知下

      c.setNotificationUri(getContext().getContentResolver(),uri);

      System.out.println("query");

      return c;

   }

 

   @Override

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

          String[] selectionArgs) {

      // TODOAuto-generated method stub

      return 0;

   }

 

}

FirstProvidermetaData.java

 

public class FirstProvidermetaData{

   public static final String AUTHORITY="com.bj.firstcontentprovider"; //继承了contentprovider的类的全名

   //数据库名称 

   public static final String DATABASE_NAME = "FirstProvider.db"; 

   //数据库的版本  

   public static final int DATABASE_VERSION= 1; 

   //表名  

   public static final String USERS_TABLE_NAME= "users"; 

   

   public static final class UserTableMetaDataimplements BaseColumns{

      //表名

      public static final String TABLE_NAME="users";

      //访问该ContentProviderURI

      public static final Uri CONTENT_URI=Uri.parse("content://"+AUTHORITY+"/users");

      

      public static final String CONTENT_TYPE="vnd.android.cursor.dir/vnd.firstprovider.user";

      public static final String CONTENT_TYPE_ITEM="vnd.android.cursor.item/vnd.firstprovider.user";

      //列名,在users表中添加一个名为name的列   

      public static final String USER_NAME="name";

      //默认排序方式

      public static final String DEFAULT_SORT_ORDER="_id desc";

   }

 

}

 

DatabaseHelper.javaAndroid学习十六:SQLite使用方法


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值