zoukankan      html  css  js  c++  java
  • 安卓开发_深入理解Content Provider

      

    一、Content Provider概述

    Content Provider用于保存和获取数据,并使其对所有应用程序可见,这是不同应用程序之间共享数据的唯一方式,因为在Android中没有提供所有应用可以共同访问的公共存储区域

    1、  Content Provider内部的数据如何保存是由其设计者决定的,而所有的的Content Provider都实现一组通用的方法,用来提供数据的增删改查操作

    2、  客户端如果要使用这些操作方法,可以通过ContentProvider对象实现对 Content Provider的操作,而开发人员可以通过调用getContentResolver()方法来获得ContentProvider对象

    即:ContentResolver cr = getContentProvider();

    3、  不同进程之间的通信由ContentResolver类和ContentProvider类处理

    二、Content Provider提供数据的数据模型

    _ID

    NAME

    AGE

    001

    Alice

    17

    002

    Mark

    20

    003

    Tom

    11

    可以看出使用的是基于数据库模型的简单表格来提供其中的数据 行:记录 列:字段

    *每条记录都包含一个_ID字段,用于在表中唯一标识该记录

    ID字段前包含一个下划线_ ,这是必须有的,不能不写

    三、URI

    1、  每个Content Provider提供公共的URI(使用URI类包装)来唯一标识其数据集

    2、  URI常量用于所有与Content Provider的交互,每个Content Provider方法都是用URI作为方法的第一个参数,这个参数(URI)用来标识ContentResolver应该使用Content Provider中的哪一个数据表

    3、  URI: content://com.xqx.mycontent/dba/010

    (1)content:// :标准的前缀,用于标识该数据由Content Provider管理,固定值,不用修改

    (2)com.xqx.mycontent :URI的authority部分,用于标识Content Provider,在清单文件的<provider>元素的authority属性中声明该authority ,对于第三方应用,该部分为完整的类名(全部小写字母)

    (3)/dba :路径部分,用于决定哪类数据被请求,如果Content Provider只提供一种数据类型,则可省略该部分、如果提供多种类型,则由多部分组成

    (4)/010 :被请求的特定记录的ID ,如果请求的记录不限于单条记录(比如查询全部字段),该部分不用写

    四、预定义Content Provider

    1、  安卓系统提供了很多预定义的Content Provider(声音,联系人,通话记录等)

    Eg:

    Browser :读取或修改书签,浏览历史或网络搜索

    CallLog :查看或更新通话记录

    Contacts: :获取修改或保存联系人信息

    MediaStore:访问图片视频音乐等

    2、  查询数据

    如果想查询Content Provider数据,必须需要三个信息

    (1)       标识该Content Provider的URI

    (2)       需要查询的数据字段的名称

    (3)       字段值数据的类型

    *如果查询特定的记录,则还需要提供该记录的ID值

    为了限制返回一条数据,可以在URI结尾添加要操作记录的ID,

    Content://…./003

    实现该功能可以使用静态方法ContentUris.withAppendedId(),返回值为一个增加了ID的URI对象

    获得数据用Cursor对象处理,它能向前或向后遍历整个查询结果集。

    3、  增加记录

    (1)       向ContentProvider中添加数据,需要使用ContentValues对象建立键值对映射,键位Content Provider中的字段,值为要添加的值

    (2)       调用ContentResolver.insert(URI,value);

    第一个参数为要操作的ContentProvider唯一标识的URI,第二个参数为ContentValues映射 ,该方法返回添加记录的完整的URI

    4、  删除记录

    (1)需要调用int delete (Uri url, String where, String[] selectionArgs)方法 ,第一个为要操作的URI ,第二个为删除的条件,第三个参数为填充值

    int delete (Uri url, “_id=?”, 11) 为删除URI 中id为11的记录

    五、  自定义Content Provider

    1、  我们从上面了解了开发人员可以使用系统给定的ContentProvide

    当然我们也可以自定义ContentProvider来共享自己的数据(当然也可以使用系统预定义的ContentProvider,管理相同的数据并且有写入权限,也可修改对应数据)

    自定义ContentProvider步骤

    (1)、建立数据存储系统

        Android提供了SQLiteOpenHelper 类帮助创建数据库,SQLiteDatabase类帮助管理数据库

    (2)、继承ContentProvider

        需要重写6个抽象方法

        

    方法

    说明

    • onCreate()

    用于初始化provider

    query()

    返回数据给调用者

    insert()

    插入新数据到ContentProvider

    updata()

    更新数据

    delete()

    从ContentProvider中删除数据

    getType()

    返回CntentProvider数据的MIME类型

      eg:

     1 package com.example.mycontentprovider;
     2 
     3 import android.content.Context;
     4 import android.database.sqlite.SQLiteDatabase;
     5 import android.database.sqlite.SQLiteOpenHelper;
     6 
     7 public class DBhelper extends SQLiteOpenHelper{
     8     public DBhelper(Context context) {
     9         super(context, "users.db", null, 1);
    10     }
    11 
    12     @Override
    13     public void onCreate(SQLiteDatabase db) {
    14         // TODO 初始化数据库
    15         db.execSQL("create table t_user(_id integer primary key,uname,upass,money)");
    16         
    17         db.execSQL("create table t_order(_id integer primary key,user_id,price,productname)");
    18         
    19         db.execSQL("insert into t_user(uname,upass,money) values('lisi','123',200)");
    20         
    21         db.execSQL("insert into t_user(uname,upass,money) values('zhangsi','1234',2000)");
    22         
    23         
    24     }
    25 
    26     @Override
    27     public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    28         // TODO 数据库升级时执行该方法
    29         if(newVersion>oldVersion)
    30         {
    31             db.execSQL("drop table if exists t_user");
    32             db.execSQL("drop table if exists t_order");
    33             
    34             onCreate(db);
    35         }
    36         
    37     }
    38 
    39     
    40 
    41 }
    DBhelper类 继承SQLiteOpenHelper
      1 package com.example.mycontentprovider;
      2 
      3 import android.content.ContentProvider;
      4 import android.content.ContentUris;
      5 import android.content.ContentValues;
      6 import android.content.UriMatcher;
      7 import android.database.Cursor;
      8 import android.database.sqlite.SQLiteDatabase;
      9 import android.net.Uri;
     10 
     11 public class UserContentProvider extends ContentProvider{
     12     /*
     13      * 这里有两个数据表t_user t_order 
     14      * 给t_user Code标识1
     15      * 给t_order Code标识2
     16      * 假设当前只对表t_user操作
     17      * 
     18      */
     19     
     20     //声明该ContentProvider的唯一标识
     21     public static final String AUTHORITY="com.xqx_mydatabase";
     22     //为该组件中可以被外界访问 数据库中的资源定义Code标识
     23     public static final int CODE_USER = 1;
     24     public static final int CODE_ORDER = 2;
     25     //定义访问资源的URI匹配器,使用该类生成被访问的资源的URI
     26     private static UriMatcher uriMather;
     27     private DBhelper dbhelper;
     28     static {
     29         uriMather = new UriMatcher(UriMatcher.NO_MATCH);
     30         //CODE_USER(1)对应的URI:content://com.xqx_mydatabase/user
     31         uriMather.addURI(AUTHORITY, "user", CODE_USER);
     32         //CODE_USER(2)对应的URI:content://com.xqx_mydatabase/order
     33         uriMather.addURI(AUTHORITY, "order", CODE_ORDER);
     34     }
     35     
     36     //删除返回删除成功记录的条数
     37     @Override
     38     public int delete(Uri uri, String selection, String[] selectionArgs) {
     39         // TODO Auto-generated method stub
     40         SQLiteDatabase db = dbhelper.getWritableDatabase();
     41         if(uriMather.match(uri)==CODE_USER)
     42         {
     43             //删除t_user表中的数据,返回删除记录的条数
     44              int num = db.delete("t_user", selection, selectionArgs);
     45              return num;
     46         }
     47         return 0;
     48     }
     49 
     50     @Override
     51     public String getType(Uri uri) {
     52         // TODO Auto-generated method stub
     53         return null;
     54     }
     55     
     56     //插入记录
     57     @Override
     58     public Uri insert(Uri uri, ContentValues values) {
     59         // TODO Auto-generated method stub
     60         SQLiteDatabase db = dbhelper.getWritableDatabase();
     61         if(uriMather.match(uri)==CODE_USER)
     62         {
     63             //得到插入记录的ID
     64             long id = db.insert("t_user", null, values);
     65             //返回新插入记录的URI
     66             return ContentUris.withAppendedId(uri, id);
     67         }
     68         return null;
     69     }
     70     
     71     //创建DBhelper对象
     72     @Override
     73     public boolean onCreate() {
     74         // TODO Auto-generated method stub
     75         dbhelper = new DBhelper(getContext());
     76         return false;
     77     }
     78     
     79     //查询,返回Cursor对象
     80     @Override
     81     public Cursor query(Uri uri, String[] projection, String selection,
     82             String[] selectionArgs, String sortOrder) {
     83         // TODO Auto-generated method stub
     84         SQLiteDatabase db = dbhelper.getReadableDatabase();
     85         //得到uri对应的Code
     86         int code = uriMather.match(uri);
     87         Cursor cursor = null;
     88         switch (code) {
     89         //如果匹配CODE_USER 操作数据表t_user
     90         case CODE_USER:
     91             //查询数据表t_user
     92             cursor = db.query("t_user", projection, selection, selectionArgs, null, null, sortOrder);
     93             break;
     94         case CODE_ORDER:
     95             break;
     96         default:
     97             break;
     98         }
     99         
    100         return cursor;
    101     }
    102 
    103     //修改数据表中的数据,返回修改记录的条数
    104     @Override
    105     public int update(Uri uri, ContentValues values, String selection,
    106             String[] selectionArgs) {
    107         // TODO Auto-generated method stub
    108         SQLiteDatabase db = dbhelper.getWritableDatabase();
    109         if(uriMather.match(uri)==CODE_USER)
    110         {
    111             return db.update("t_user", values, selection, selectionArgs);
    112         }
    113         
    114         return 0;
    115     }
    116 
    117 }
    UserContentProvider.class 继承ContentProvider

    (3)、在应用程序的AndroidManifest文件中注册Content Provider

     1 <!-- 注册 ContentProvider组件 
     2               android:authorities:声明该组件的唯一标识
     3               android:permission:声明该组件的权限
     4               android:exported="true":声明该组件可以被外界应用访问
     5         -->
     6         <provider 
     7             android:name="com.xqx.UserContentProvider"
     8             android:authorities="com.xqx.users"
     9             android:permission="com.xqx.READ_WRITE"
    10             android:exported="true"
    11             />

     -----------------------------------------------------------------------------------------------

  • 相关阅读:
    什么是JDBC的最佳实践?
    如何将jquery对象转换为js对象?
    JQuery有几种选择器?
    jQuery 库中的 $() 是什么
    JS 中 == 和 === 区别是什么?
    有两张表;请用SQL查询,所有的客户订单日期最新的前五条订单记录?
    根据你以往的经验简单叙述一下MYSQL的优化?
    数据库MySQL分页时用的语句?
    LeetCode231-2的幂(水题,考察是否粗心)
    LeetCode191-位1的个数(题目有问题)
  • 原文地址:https://www.cnblogs.com/xqxacm/p/4803445.html
Copyright © 2011-2022 走看看