四大組件之一 CotentProvider

概念

ContentProvider做爲四大組件之一,他的地位不容忽視。它的做用是爲不一樣應用程序數據共享,提供統一接口 咱們其餘應用程序要調用android系統中的應用,這時候就要用到ContentProvider,也能夠咱們利用ContentProvider編寫本身的內容提供者,供其餘應用使用android

ContentProvider如何實現數據共享的

ContentProvider經過URI惟一標識其餘要訪問的數據,開發人員通常經過ContentResolver來進行操做ContentProvider,可進行增刪改查實現對數據的共享。git

ContentProvider講解

ContentProvider是一個抽象類,若是要開發本身的內容提供者都要繼承這個類並進行重寫。主要實現如下方法:github

public boolean onCreate()

在建立ContentProvider的時候進行調用sql

public Cursor query()

用來查詢指定的URI返回一個Cursor數據庫

public Uri insert()

向指定RUI的ContentProvider中插入數據bash

public int update()

用戶更新指定的RUI的數據ide

public int delete()

用戶刪除指定的RUI的數據ui

public String getType()

用於返回指定的Uri中的數據MIME類型this

自定義ContentProvider講解

咱們建立一個數據庫的ContentProvider類來實現數據共享,自定義名稱爲MyProviderspa

package com.haolin.contentprovider.sample;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;

public class MyProvider extends ContentProvider {

  private Context mContext;
  DBHelper mDbHelper = null;
  SQLiteDatabase db = null;
  public static final String AUTOHORITY = "com.haolin.contentprovider.sample.MyProvider";
  // 設置ContentProvider的惟一標識

  public static final int User_Code = 1;
  public static final int Job_Code = 2;

  // UriMatcher類使用:在ContentProvider 中註冊URI
  private static final UriMatcher mMatcher;
  static{
      mMatcher = new UriMatcher(UriMatcher.NO_MATCH);
      // 初始化
      mMatcher.addURI(AUTOHORITY,"user", User_Code);
      mMatcher.addURI(AUTOHORITY, "job", Job_Code);
  }

  // 如下是ContentProvider的6個方法

  /**
   * 初始化ContentProvider
   */
  @Override
  public boolean onCreate() {

      mContext = getContext();
      // 在ContentProvider建立時對數據庫進行初始化
      // 運行在主線程,故不能作耗時操做,此處僅做展現
      mDbHelper = new DBHelper(getContext());
      db = mDbHelper.getWritableDatabase();

      // 初始化兩個表的數據(先清空兩個表,再各加入一個記錄)
      db.execSQL("delete from user");
      db.execSQL("insert into user values(1,'Carson');");
      db.execSQL("insert into user values(2,'Kobe');");

      db.execSQL("delete from job");
      db.execSQL("insert into job values(1,'Android');");
      db.execSQL("insert into job values(2,'iOS');");

      return true;
  }

  /**
   * 添加數據
   */

  @Override
  public Uri insert(Uri uri, ContentValues values) {

      // 根據URI匹配 URI_CODE,從而匹配ContentProvider中相應的表名
      // 該方法在最下面
      String table = getTableName(uri);

      // 向該表添加數據
      db.insert(table, null, values);

      // 當該URI的ContentProvider數據發生變化時,通知外界(即訪問該ContentProvider數據的訪問者)
      mContext.getContentResolver().notifyChange(uri, null);

//        // 經過ContentUris類從URL中獲取ID
//        long personid = ContentUris.parseId(uri);
//        System.out.println(personid);

      return uri;
      }

  /**
   * 查詢數據
   */
  @Override
  public Cursor query(Uri uri, String[] projection, String selection,
                      String[] selectionArgs, String sortOrder) {
      // 根據URI匹配 URI_CODE,從而匹配ContentProvider中相應的表名
      // 該方法在最下面
      String table = getTableName(uri);
      // 查詢數據
      return db.query(table,projection,selection,selectionArgs,null,null,sortOrder,null);
  }

  /**
   * 更新數據
   */
  @Override
  public int update(Uri uri, ContentValues values, String selection,
                    String[] selectionArgs) {
      // 因爲不展現,此處不做展開
      return 0;
  }

  /**
   * 刪除數據
   */
  @Override
  public int delete(Uri uri, String selection, String[] selectionArgs) {
      // 因爲不展現,此處不做展開
      return 0;
  }

  @Override
  public String getType(Uri uri) {

      // 因爲不展現,此處不做展開
      return null;
  }

  /**
   * 根據URI匹配 URI_CODE,從而匹配ContentProvider中相應的表名
   */
  private String getTableName(Uri uri){
      String tableName = null;
      switch (mMatcher.match(uri)) {
          case User_Code:
              tableName = DBHelper.USER_TABLE_NAME;
              break;
          case Job_Code:
              tableName = DBHelper.JOB_TABLE_NAME;
              break;
      }
      return tableName;
      }
  }


複製代碼
  • ContentProvider做爲四大組件之一,咱們必須再AndroidManifest.xml文件中進行註冊
<provider
          android:authorities="com.haolin.contentprovider.sample.MyProvider"
          android:name=".MyProvider"
          android:exported="true"/>
          
複製代碼

這裏的authorities惟一標識該內容提供者,這樣其它的應用才能夠找到該內容提供者並操做它的數據;exported爲true當前內容提供者能夠被其它應用使用,默認爲true

操做ContentProvider裏的數據

咱們在MainActivity中來操做ContentProvider數據 或者新建個項目也可直接操做

/*
       * 對user表進行操做
       */

      // 設置URI
      Uri uri_user = Uri.parse("content://com.haolin.contentprovider.sample.MyProvider/user");

      // 插入表中數據
      ContentValues values = new ContentValues();
      values.put("_id", 3);
      values.put("name", "Iverson");


      // 獲取ContentResolver
      ContentResolver resolver =  getContentResolver();
      // 經過ContentResolver 根據URI 向ContentProvider中插入數據
      resolver.insert(uri_user,values);

      // 經過ContentResolver 向ContentProvider中查詢數據
      Cursor cursor = resolver.query(uri_user, new String[]{"_id","name"}, null, null, null);
      assert cursor != null;
      while (cursor.moveToNext()){
          System.out.println("query book:" + cursor.getInt(0) +" "+ cursor.getString(1));
          // 將表中數據所有輸出
      }
      cursor.close();
      // 關閉遊標

      /*
       * 對job表進行操做
       */
      // 和上述相似,只是URI須要更改,從而匹配不一樣的URI CODE,從而找到不一樣的數據資源
      Uri uri_job = Uri.parse("content://com.haolin.contentprovider.sample.MyProvider/job");

      // 插入表中數據
      ContentValues values2 = new ContentValues();
      values2.put("_id", 3);
      values2.put("job", "NBA Player");

      // 獲取ContentResolver
      ContentResolver resolver2 =  getContentResolver();
      // 經過ContentResolver 根據URI 向ContentProvider中插入數據
      resolver2.insert(uri_job,values2);

      // 經過ContentResolver 向ContentProvider中查詢數據
      Cursor cursor2 = resolver2.query(uri_job, new String[]{"_id","job"}, null, null, null);
      assert cursor2 != null;
      while (cursor2.moveToNext()){
          System.out.println("query job:" + cursor2.getInt(0) +" "+ cursor2.getString(1));
          // 將表中數據所有輸出
      }
      cursor2.close();
      // 關閉遊標
      
複製代碼

這樣咱們能夠對ContentProvider進行增刪改查等操做。

ContentObserver

  • 註冊ContentObserver來監聽對應uri的數據變化,這步不是必須的,若是不須要監聽數據變化也能夠不註冊

  • 首先獲取ContentResolver對象 getContentResolver() 在進行註冊Observer resolver.registerContentObserver(uri_user,true,new TestContentObs(handler));

  • 咱們須要建立個類繼承ContentObserver

package com.haolin.contentprovider.testcontentprovider;

import android.database.ContentObserver;
import android.net.Uri;
import android.os.Handler;
import android.os.Message;

/**
* 做者:haoLin_Lee on 2019/05/12 12:18
* 郵箱:Lhaolin0304@sina.com
* class:
*/
public class TestContentObs extends ContentObserver {

  Handler handler;
  public TestContentObs(Handler handler) {
      super(handler);
      this.handler = handler;
  }

  @Override
  public void onChange(boolean selfChange, Uri uri) {
      super.onChange(selfChange, uri);

      Message message = Message.obtain();
      message.obj = uri;
      handler.sendMessage(message);
  }
}

複製代碼

若是數據庫內容有更新,ContentObserver在收到數據變化的通知後經過Handler機制來通知主線程更新UI

感謝你們的閱讀

給個讚唄 有問題及時反饋,謝謝你們

關注我 GitHub

相關文章
相關標籤/搜索