0119ContentProvider

0119ContentProvider 提供访问数据的一个统一的接口 在不同的应用程序之间共享数据

每一组数据都对应一个ContentProvider,有很多的ContentProvider 如何找到对应的ContentProvider? URL,统一资源标识符。对每一个资源起一个单独的名字,每一个ContentProvider都有一个公共的URL

Android所提供的ContentProvider都存放在Android.provider包当中 得到URL的一个常量,比如CONTENT_URL,得到这个常量就可以得到代表这个ContentProvider的URL,得到这个URL就使用这个ContentProvider提供的方法

得到ContentProvider后,根据其所提供的函数,可以增删改查

query() 查询 insert() 插入 update() 更新 delete() 删除 getType() 得到数据类型 onCreate()  创建时的回调函数?? 在创建ContentProvider时要做的一些事情

自己实现ContentProvider不多,但是如果不知道其工作原理,如何实现,用起来就会一头雾水

实现ContentProvider的过程

1,定义一个CONTENT_URI常量

2,定义一个类,继承ContentProvider

3,实现query,insert,update,delete,getType,onCreate方法

4,在AndroidManifest.xml当中进行声明

FirstContentProvider.java FirstContentProvider继承了ContentProvider这个类

FirstProviderMetaData.java定义了ContentProvider所需要使用的常量

首先定义一个CONTENT_URI 实际上是一个字符串,然后转换为URI类型,这个字符串必须是唯一的 content://com.example.codelab.transportationsprovider  第一,content:// 第二,需要完整的类名

需要有_id作为唯一的标示符 如果用SQLite _id可以定义为INTERGER PRIMARY KEY AUTOINCREMENT 即整形数据 关键字 自增长

数据类型 访问整张表的数据 "vnd.android.cursor.dir/vnd.firstprovider.user"   dir是整张表格

如果要访问Provider里面其中一个数据的话 "vnd.android,cursor.item/vnd.firstprovider.user"  item是其中一条数据

URIMatcher 作用 检测  URI是否符合我们的标准 原理是将一个URL和一个数字相关联

定义一个规则 uriMatcher.addURI(authority,目录路径,与之对应整型变量的值)//此为定义的一个规则 public String getType(Uri uri)方法中 uriMatcher.match(uri)进行匹配

UriMatcher就是起了一个规则,给每一个Uri一个整型变量 如果规则中“与之对应整型变量的值”与 case 匹配,则返还相应的值

定义一个 HashMap public static HashMap<String,String> userProjectionMap;//声明一个 HashMap static {     userProjectionMap= new HashMap<String,String>();     userProjectionMap.put(UserTableMetaData._ID,UserTableMetaDate._ID);     userProjectionMap.put(UserTableMetaData.USER_NAME,UserTableMetaDate.USER_NAME); }//给ContentProvider这张表的列起一个别名

getContentResolve();获得ContentResolve() ,这个可以操作ContentProvider

public Uri insert(要向哪一个Uri插入即向哪一个ContentProvider,值) //该函数的返回值是一个Uri,这个Uri表示的是刚刚使用这个函数所插入的数据 //content://mars.cp.FirstContentProvider/users/1  这个以代表新插入的行号 db.insert();该函数的返回值是新插入行的行号

SQLiteQueryBuilder qb=new SQLiteQueryBuilder();创建查询的语句,相当于一个查询语句

qb.appendWhere();//添加where字句

CPActivity.java

 1 package com.example.test_cp;
 2 
 3 import com.example.test_cp.FirstProviderMetaData.UserProvidermetaData;
 4 
 5 import android.net.Uri;
 6 import android.os.Bundle;
 7 import android.app.Activity;
 8 import android.content.ContentValues;
 9 import android.database.Cursor;
10 import android.view.Menu;
11 import android.view.View;
12 import android.view.View.OnClickListener;
13 import android.widget.Button;
14 
15 public class CPActivity extends Activity {
16 
17     private Button myButton;
18     private Button myButton2;
19     @Override
20     protected void onCreate(Bundle savedInstanceState) {
21         super.onCreate(savedInstanceState);
22         setContentView(R.layout.activity_cp);
23         myButton=(Button)findViewById(R.id.myButton);
24         myButton2=(Button)findViewById(R.id.myButton2);
25         myButton.setOnClickListener(new MyButtonClickListener());
26         myButton2.setOnClickListener(new MyButton2ClickListener());
27         
28     }
29     
30     public class MyButtonClickListener implements OnClickListener{
31 
32         @Override
33         public void onClick(View v) {
34             // TODO Auto-generated method stub
35             ContentValues values=new ContentValues();
36             //将张三这个值放到values 里面    键值对
37             values.put(FirstProviderMetaData.UserProvidermetaData.USER_NAME, "zhangsan");
38             Uri uri=getContentResolver()
39                     .insert(UserProvidermetaData.CONTENT_URI, values);
40             //这样就可以得到一个ContentResolver对象,
41             //可以操作ContentProvider,比如用ContentProvider里面的insert()
42             //把代表FirestContentProvider的uri传入,这样就可以调用FirstContentProvider的insert方法
43             System.out.println("uri--->"+uri.toString());
44         }
45         
46     }
47     
48     public class MyButton2ClickListener implements OnClickListener{
49 
50         @Override
51         public void onClick(View v) {
52             // TODO Auto-generated method stub
53             Cursor c=getContentResolver().query(FirstProviderMetaData.UserProvidermetaData.CONTENT_URI, null, null, null, null);
54             while(c.moveToNext()){
55                 System.out.println(c.getString(c.getColumnIndex(UserProvidermetaData.USER_NAME)));
56             //getString里面是列的编号,列的编号要挺过getColumnIndex()得到;
57             }        
58         }
59         
60     }
61 
62 
63 
64 }

FirstContentProvider.java

  1 package com.example.test_cp;
  2 import java.util.HashMap;
  3 
  4 import com.example.mars_sqlite.db.DatebaseHelper;//引入另一个包
  5 import com.example.test_cp.FirstProviderMetaData.UserProvidermetaData;
  6 
  7 import android.content.ContentProvider;
  8 import android.content.ContentUris;
  9 import android.content.ContentValues;
 10 import android.content.UriMatcher;
 11 import android.database.Cursor;
 12 import android.database.SQLException;
 13 import android.database.sqlite.SQLiteDatabase;
 14 import android.database.sqlite.SQLiteQueryBuilder;
 15 import android.net.Uri;
 16 import android.text.TextUtils;
 17 
 18 public class FirstContentProvider extends ContentProvider{
 19     DatebaseHelper dh=null;
 20     public static UriMatcher uriMatcher=null;
 21     public static final int INCOMING_USER_COLLECTION=1;
 22     public static final int INCOMING_USER_SINGLE=2;
 23     /**
 24      * URIMatcher 作用 检测  URI是否符合我们的标准
 25                              原理是将一个URL和一个数字相关联
 26      */
 27     // 定义一个规则
 28     static{
 29         uriMatcher=new UriMatcher(UriMatcher.NO_MATCH);
 30         uriMatcher.addURI(FirstProviderMetaData.AUTHORITY, "users", INCOMING_USER_COLLECTION);
 31         uriMatcher.addURI(FirstProviderMetaData.AUTHORITY, "users/#", INCOMING_USER_SINGLE);
 32     }
 33     
 34     public static HashMap<String,String>  userProjectionMap;
 35     static {
 36         userProjectionMap=new HashMap<String,String>();
 37         userProjectionMap.put(UserProvidermetaData._ID, UserProvidermetaData._ID);
 38         userProjectionMap.put(UserProvidermetaData.USER_NAME, UserProvidermetaData.USER_NAME);
 39         //第一个是键,第二个是值,可以参考0113,老师讲师起别名
 40     }
 41     
 42     
 43     /**
 44      * UriMatcher就是起了一个规则,给每一个Uri一个整型变量
 45      * 如果规则中“与之对应整型变量的值”与 case 匹配,则返还相应的值
 46      */
 47     //下面的代码这个实例没有用到没有
 48     @Override
 49     public String getType(Uri uri) {
 50         // TODO Auto-generated method stub
 51         
 52         switch(uriMatcher.match(uri)){
 53         case INCOMING_USER_COLLECTION:
 54             return FirstProviderMetaData.UserProvidermetaData.CONTENT_TYPE;
 55         case INCOMING_USER_SINGLE:
 56             return FirstProviderMetaData.UserProvidermetaData.CONTENT_TYPE_ITEM;
 57         default:
 58             throw new IllegalArgumentException("Unknow String" + uri);    
 59         }
 60         
 61         
 62     }
 63     
 64     
 65     
 66   
 67     
 68     @Override
 69     public Cursor query(Uri uri, String[] projection, String selection,
 70             String[] selectionArgs, String sortOrder) {
 71         //projection是列有哪些
 72         //selcetion是where字句的内容 selectionArgs 前面查询的占位符所对应的参数
 73         // TODO Auto-generated method stub
 74         SQLiteQueryBuilder qb=new SQLiteQueryBuilder();//创建查询的语句,相当于一个查询语句
 75         switch(uriMatcher.match(uri)){//要知道是查询的一系列的user对象还是单个的user对象
 76         case INCOMING_USER_COLLECTION:
 77             qb.setTables(UserProvidermetaData.TABLE_NAME);//设置要查询哪一张表格
 78             qb.setProjectionMap(userProjectionMap);
 79             //表格的每一列起一个别名projectionMap
 80             break;//忘记添加这个导致进入第二个,get(1)不存在,得不到发生错误
 81             //uri-->content://com.example.test_cp.FirstContentProvider/users所以进入第一个
 82         case INCOMING_USER_SINGLE://这个没有进入
 83             qb.setTables(UserProvidermetaData.TABLE_NAME);
 84             qb.setProjectionMap(userProjectionMap);
 85             //coneten://com.example.test_cp.FirstContentProvider/users/1
 86             //users/1就是path部分 users是第0个元素 get(1)就是得到users/#中的#
 87             qb.appendWhere(UserProvidermetaData._ID+"="+uri.getPathSegments().get(1));
 88             //相当于一个查询语句
 89         default:
 90             break;
 91             
 92         
 93         }
 94         
 95         String orderBy;
 96         if(TextUtils.isEmpty(sortOrder))//如果传入的sortOrder是空的话
 97         {
 98             orderBy=UserProvidermetaData.DEFUALT_SORT_ORDER;
 99             
100         }else{orderBy=sortOrder;}
101         SQLiteDatabase db=dh.getWritableDatabase();
102         Cursor c=qb.query(db, projection, selection, selectionArgs, null, null, sortOrder);
103         //0116 db要查询的数据库 projection 要查询的列 selection是where字句 selectionArgs是前面占位符对应的参数
104         c.setNotificationUri(getContext().getContentResolver(), uri);//通知修改
105         System.out.println("b");
106         return c;
107         
108             
109     }
110 
111     @Override
112     public boolean onCreate() {
113         // TODO Auto-generated method stub
114         dh=new DatebaseHelper(getContext(),FirstProviderMetaData.DATABASE_NAME);
115         //context 在你的环境中可以通过context得到运行环境的信息
116         return true;
117     }
118     
119     
120     
121 
122     @Override
123     public Uri insert(Uri uri, ContentValues values) {
124         // TODO Auto-generated method stub
125         SQLiteDatabase db=dh.getWritableDatabase();
126         //向表中插入值
127         int rowid=(int)db.insert(FirstProviderMetaData.USERS_TABLE_NAME,null,values);
128         //该函数的返回值是新插入行的行号
129         if(rowid>0)
130         {
131             Uri insertedUserUri=ContentUris.withAppendedId(UserProvidermetaData.CONTENT_URI, rowid);
132             getContext().getContentResolver().notifyChange(uri,null );//通知数据的修改
133             return insertedUserUri;//返回新插入数据的uri
134         }
135         throw new SQLException("ERR Uri" + uri);
136     }
137 
138     @Override
139     public int delete(Uri uri, String selection, String[] selectionArgs) {
140         // TODO Auto-generated method stub
141         return 0;
142     }
143 
144     @Override
145     public int update(Uri uri, ContentValues values, String selection,
146             String[] selectionArgs) {
147         // TODO Auto-generated method stub
148         return 0;
149     }
150     
151 }

FirstProviderMetaData.java

 1 package com.example.test_cp;
 2 
 3 import android.net.Uri;
 4 import android.provider.BaseColumns;
 5 
 6 public class FirstProviderMetaData{
 7     //要写完整的类名
 8     public static final String AUTHORITY="com.example.test_cp.FirstContentProvider";
 9     //数据库名字,因为我们要用数据库来作为ContentProvider底层的存储方式
10     public static final String DATABASE_NAME="FirstProvider.db";
11     //数据库版本
12     public static final int DATABASE_VERSION=1;
13     //表名
14     public static final String USERS_TABLE_NAME="users";
15     //内部类,要实现的属性或者方法在接口中已经有,则可以定义一个内部类来实现此接口
16     public static final class UserProvidermetaData implements BaseColumns {
17         //BaseColumns定义了_ID  这个是The unique ID for a row
18         public static final String TABLE_NAME="users";
19         //访问该provider的Uri , content+AUTHORTY+字表的名字
20         //表示取得这样一个ContentProvider的uri对象
21         public static final Uri CONTENT_URI=Uri.parse("content://"+AUTHORITY+"/users");
22         //这个是定义访问整张表的数据类型,后面的名字可以随便起
23         public static final String CONTENT_TYPE="vnd.android.cursor.dir/vnd.firstprovider.user";
24         //定义访问provider里面的某一条数据的数据类型
25         public static final String CONTENT_TYPE_ITEM="vnd.android.cursor.item/vnd.firstprovider.user";
26         //列名,在users里面存放name这一列
27         public static final String USER_NAME="name";
28         //定义默认排序
29         public static final String DEFUALT_SORT_ORDER="_id desc";
30     }
31     
32 }

DatabaseHelpr.java

 1 //第一,getReadableDatabase(),getWritableDatabase()可以获得SQLiteDatabse对象,通过该对象可以对数据库进行操作
 2 //即通过数据库助手类,可以通过他的两个函数得到可读或者可写的数据库对象
 3 //第二,提供了onCreate()和onUpgrade()两个回调函数,允许我们在创建和升级数据库时,进行自己的操作
 4 //自定义SQLiteOpenHelper,必需要实现onCreate(), onUpgrade(),可以选择实现onOpen。 
 5 package com.example.mars_sqlite.db;
 6 
 7 import com.example.test_cp.FirstProviderMetaData;
 8 import com.example.test_cp.FirstProviderMetaData.UserProvidermetaData;
 9 
10 import android.content.Context;
11 import android.database.sqlite.SQLiteDatabase;
12 import android.database.sqlite.SQLiteDatabase.CursorFactory;
13 import android.database.sqlite.SQLiteOpenHelper;
14 //A helper class to manage database creation and version management.
15 
16 public class DatebaseHelper extends SQLiteOpenHelper
17 {
18 
19     public DatebaseHelper(Context context, String name, CursorFactory factory,
20             int version) {
21         super(context, name, factory, version);
22         // TODO Auto-generated constructor stub
23     }
24     
25     public DatebaseHelper(Context context,String name,int version)
26     
27     {
28         this(context ,name ,null, version);//调用上面四个参数的构造函数
29     }
30     public DatebaseHelper(Context context,String name )
31     {
32         this (context ,name ,1);//调用上面三个参数的构造函数
33     }
34     
35     //下面函数要创建实际上是在第一次得到SQliteDatebase对象的时候才会调用这个方法,
36     //意思就是仅仅生成DatebaseHelper(继承SQliteOpenHelper)的对象是无法执行这两个函数,
37     //只有调用getReadableDatebase 和getWritableDatebase时候才会调用这些方法
38     @Override
39     public void onCreate(SQLiteDatabase db) {
40         // TODO Auto-generated method stub
41         System.out.println("create a datebase");
42         //db.execSQL("create table user(id int,name verchar(20))");
43         db.execSQL("create table"+" "+FirstProviderMetaData.USERS_TABLE_NAME+
44                 "("+UserProvidermetaData._ID+" "+"INTEGER PRIMARY KEY AUTOINCREMENT," +
45                             UserProvidermetaData.USER_NAME+" "+"verchar(20));");//数据库db执行数据库语句
46     }//这里创建表名为user
47      //当更新这张表时候,要更改scheme version 即模式版本,不然无法更新
48     //Called when the database needs to be upgraded.
49     //The implementation should use this method to drop tables,
50     //add tables, or do anything else it needs to upgrade to the new schema version
51     @Override
52     public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
53         // TODO Auto-generated method stub
54         System.out.println("onUpgrade a datebase");
55     }
56     }

经过测试,以下语句必须添加在AndroidManifest.xml中

<provider
            android:name="com.example.test_cp.FirstContentProvider"
            android:authorities="com.example.test_cp.FirstContentProvider"
            />

原文地址:https://www.cnblogs.com/kyxyes/p/2919825.html