第六周随笔(2)--Content Provider

Content Provider:内容提供者

  • 应用程序间共享数据的一种方式
  • 为存储和获取数据提供了统一的接口
  • Android为常见的一些数据提供了默认的 Content Provider
  • 四大组件之一

定义

  • 内容提供者将一些特定的应用程序数据供给其他应用程序使用
  • 数据可以存储于文件系统、SQLite数据库或其他方式
  • 内容提供者继承于ContentProvider基类,为其他应用程序取用和存储它管理的数据实现了一套标准方法
  • 应用程序并不是直接调用这些方法,而是使用ContentResolver对象,调用它的方法作为替代
  • ContentResolver 可以与任意内容提供者进行会话,与其合作来对所有相关交互通讯进行管理

ContentProvider实现过程

Database --> Uri --> UriMatcher --> ContentProvider -- > query/insert/update/delete --> AndroidManifest.xml


系统提供的Provider

系统提供的Provider

获取系统的通讯录信息

public class PhoneBookInfo extends AppCompatActivity {
   @Override    
   protected void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState);      
        setContentView(R.layout.activity_phone_book_info);  
        ListView lvInfo = (ListView) findViewById(R.id.phoneBookInfo_lvInfo);        
        List<String> stringList = new ArrayList<>();      
        ArrayAdapter<String> arrayAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, stringList); 
        lvInfo.setAdapter(arrayAdapter);  

        //查询通讯录数据
        //由于要读取通讯录,所以要在manifest中加上"android.permission.READ_CONTACTS"的权限 
        Cursor cursor = getContentResolver().query(      
                  ContactsContract.CommonDataKinds.Phone.CONTENT_URI,                
                  null,null,null,null);  
        if (cursor!=null && cursor.moveToFirst()){  
            for (int i = 0; i < cursor.getCount(); i++) {   
                String disPlayName = cursor.getString(            
                        cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME) 
                        );
                String number = cursor.getString(
                        cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.NUMBER)  
                        );    
                arrayAdapter.add(disPlayName + "\n" + number);     
                cursor.moveToNext(); 
             }
         }
     }
  }

自定义Content Provider

URI后面还以加上 *** 或 #分别表示:

  • *:表示匹配任意长度的任意字符
  • <code>#</code>:表示匹配任意长度的数字

  1. DataBase:创建一个继承SQLiteOpenHelper的类,并创建<code>user</code>、<code>book</code>两个表。

    public class DataBaseHelper extends SQLiteOpenHelper {
        public static final String DATABASE = "test.db"; 
        public static final int VERSION = 1;
        public static final String TABLENAME_USER = "user";
        public static final String USER_NAME = TABLENAME_USER + "_name"; 
        public static final String USER_AGE = TABLENAME_USER + "_age";  
        public static final String TABLENAME_BOOK = "book";
        public static final String BOOK_NAME = TABLENAME_BOOK + "_name"; 
        public static final String BOOK_WRITER = TABLENAME_BOOK + "_writer";
        public DataBaseHelper(Context context) {
           super(context, DATABASE, null, VERSION);
        } 
        @Override
        public void onCreate(SQLiteDatabase db) {
           db.execSQL("create table " + TABLENAME_USER + " (" + USER_NAME + " TEXT not null, " +
                          USER_AGE + " TEXT not null  )"   
                     ); 
           db.execSQL("create table " + TABLENAME_BOOK + " (" + BOOK_NAME + " TEXT not null, " + 
                          BOOK_WRITER + " TEXT not null ) " 
                     ); 
        }
        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {  
        }
    }
    
  2. Uri:创建UriList.java


    UriList.Java
  3. 创建一个继承ContentProvider的类,然后设置UriMatcher和完善重构方法:

    public class TestContentProvider extends ContentProvider {  
       //初始UriMatcher
       private static UriMatcher sUriMatcher; 
       public static final int UriMatcher_CODE_USER = 1; 
       public static final int UriMatcher_CODE_BOOK = 2; 
       static {
           sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);  
           sUriMatcher.addURI(UriList.AUTHORITY, DataBaseHelper.TABLENAME_USER, UriMatcher_CODE_USER);   
           sUriMatcher.addURI(UriList.AUTHORITY, DataBaseHelper.TABLENAME_BOOK, UriMatcher_CODE_BOOK); 
       } 
    
      private DataBaseHelper mDataBaseHelper; 
      @Override    
      public boolean onCreate() {  
         //获取数据库
         mDataBaseHelper = new DataBaseHelper(getContext());  
             return true;   
         } 
         @Nullable
         @Override
         public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { 
            //从数据库中query
            Cursor cursor = mDataBaseHelper.getReadableDatabase().query(getTableName(uri), projection, selection, selectionArgs, null, null, sortOrder);  
            return cursor;  
         }
         @Nullable
         @Override
         public String getType(Uri uri) {
            return null;
         } 
         @Nullable 
         @Override 
         public Uri insert(Uri uri, ContentValues values) {
            SQLiteDatabase sqLiteDatabase = mDataBaseHelper.getWritableDatabase(); 
            Long id; 
            id = sqLiteDatabase.insert(getTableName(uri), null, values);  
            //“withAppendedId”:将uri和id连接起来(即uri/id)
            //“parseId(Uri contentUri)”:这个方法负责把contentURI 后边的id解析出来,即返回值是“id”
            return ContentUris.withAppendedId(uri, id); 
         } 
         @Override  
         public int delete(Uri uri, String selection, String[] selectionArgs) {  
            if(TextUtils.isEmpty(getTableName(uri))){ 
                return -1;  
            }
            int count = mDataBaseHelper.getWritableDatabase().delete(getTableName(uri), selection, selectionArgs);        return count;  
         }
         @Override 
         public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 
            return mDataBaseHelper.getWritableDatabase().update(getTableName(uri), values, selection, selectionArgs); 
         }
         //获取表名
         private String getTableName(Uri uri) {
             int code = sUriMatcher.match(uri);  
             String tableName = "";
             switch (code) {  
                 case UriMatcher_CODE_USER:  
                      tableName = DataBaseHelper.TABLENAME_USER;     
                      break; 
                 case UriMatcher_CODE_BOOK:  
                      tableName = DataBaseHelper.TABLENAME_BOOK;    
                      break; 
             }
             return tableName;
        }
    }
    
  4. 设置完ContentProvider之后就可以在相应功能里进行query/insert/update/delete方法,如:

    @Override
    public void onClick(View v) {  
       ContentResolver contentResolver = getContentResolver(); 
       switch (v.getId()){ 
       //查询    
       case R.id.provider_btnQuery:  
           mStringList.clear(); 
           Cursor cursor = contentResolver.query(UriList.Book_Uri,null,null,null,null);   
           if (cursor!= null && cursor.moveToFirst()){  
                String KeyValue1 = cursor.getString(cursor.getColumnIndexOrThrow(DataBaseHelper.BOOK_NAME));             
                String KeyValue2 = cursor.getString(cursor.getColumnIndexOrThrow(DataBaseHelper.BOOK_WRITER));        
                mStringList.add(KeyValue1+"\n"+KeyValue2);   
                cursor.moveToNext();  
           }     
           mAdapter.notifyDataSetChanged();  
           break; 
       //删除
       case R.id.provider_btnDelet:   
           contentResolver.delete(UriList.Book_Uri, null, null);     
           break;  
       //插入 
       case R.id.provider_btnInsert:     
           ContentValues contentValues = new ContentValues();  
           contentValues.put(DataBaseHelper.BOOK_NAME, mEdtKeyValue1.getText().toString());    
           contentValues.put(DataBaseHelper.BOOK_WRITER, mEdtKeyValue2.getText().toString());      
           contentResolver.insert(UriList.Book_Uri, contentValues); 
           break; 
       //修改   
       case R.id.provider_btnUpdate: 
           ContentValues values = new ContentValues();       
           values.put(DataBaseHelper.BOOK_NAME, mEdtKeyValue1.getText().toString());  
           values.put(DataBaseHelper.BOOK_WRITER, mEdtKeyValue2.getText().toString());      
           contentResolver.update(UriList.Book_Uri, values, null, null);   
           break; 
       }
    }
    
  5. 最后记得在manifest.xml中声明ContentProvider:
    要注意的是<code>authorities</code>的值是与上面的<code>AUTHORITY</code>的值一样;
    <code>exported</code>设置为<code>true</code>可以跨应用使用这个ContentProvider。


    声明ContentProvider
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,311评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,339评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,671评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,252评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,253评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,031评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,340评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,973评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,466评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,937评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,039评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,701评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,254评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,259评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,497评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,786评论 2 345

推荐阅读更多精彩内容