• 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"
                />

  • 相关阅读:
    剑指offer63:数据流中的中位数
    剑指offer62:二叉搜索树的第k个结点,二叉搜索树【左边的元素小于根,右边的元素大于根】
    剑指offer61:序列化二叉树
    关于手机拍摄的图片在处理过程中出现问题的解决方法
    一道逻辑思考题
    鼠标右键无反应解决方法
    六大设计原则
    开源镜像网站
    获取当前文件夹下的文件名称
    wget使用方法
  • 原文地址:https://www.cnblogs.com/kyxyes/p/2919825.html
Copyright © 2020-2023  润新知