zoukankan      html  css  js  c++  java
  • ContentProvider初步

    摘自:http://blog.sina.com.cn/s/blog_5688414b0100xagp.html

    一、Content Provider基本概念 

    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包中。 将其分为ABCD 4个部分:

    Android学习十九:ContentProvider初步

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

     BURI 的标识,它定义了是哪个Content Provider提供这些数据。对于第三方应用程序,为了保证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 

    public class 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 Activity19Activity extends 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 FirstContentProvider extendsContentProvider {

        // 当别的程序来访问这个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, ContentValues values) {

           // 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 UserTableMetaData implements BaseColumns{

           //表名

           public static final String TABLE_NAME="users";

           //访问该ContentProviderURI

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

          

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

           public static final StringCONTENT_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";

        }

     

    }

     

  • 相关阅读:
    基于centos的freeradius高可用lvs(UDP)
    sql server 2012的AlwaysOn高可用
    python基础题型一
    用户访一个APP或者网页流程示意图
    DNS解析流程
    crontab的定时任务实例
    Xcode设置
    Nvidia Nsight + .NET
    C++ Pointer-to-Member Selector
    C++11
  • 原文地址:https://www.cnblogs.com/qchy/p/2984200.html
Copyright © 2011-2022 走看看