国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統(tǒng) > Android > 正文

Android 中自定義ContentProvider與ContentObserver的使用簡單實(shí)例

2019-10-22 18:28:34
字體:
供稿:網(wǎng)友

Android 中自定義ContentProvider與ContentObserver的使用簡單實(shí)例

示例說明:

該示例中一共包含兩個工程。其中一個工程完成了自定義ContentProvider,另外一個工程用于測試該自定義ContentProvider且在該工程中使用了ContentObserver監(jiān)聽自定義ContentProvider的數(shù)據(jù)變化

以下代碼為工程TestContentProvider

ContentProviderTest如下:

package cn.testcontentprovider; import android.content.ContentProvider; import android.content.ContentUris; import android.content.ContentValues; import android.content.UriMatcher; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.net.Uri; /**  * Demo描述:  * 自定義ContentProvider的實(shí)現(xiàn)  * ContentProvider主要用于在不同的應(yīng)用程序之間共享數(shù)據(jù),這也是官方推薦的方式.  *  * 注意事項(xiàng):  * 1 在AndroidManifest.xml中注冊ContentProvider時的屬性  *  android:exported="true"表示允許其他應(yīng)用訪問.  * 2 注意*和#這兩個符號在Uri中的作用  *  其中*表示匹配任意長度的字符  *  其中#表示匹配任意長度的數(shù)據(jù)  *  所以:  *  一個能匹配所有表的Uri可以寫成:  *  content://cn.bs.testcontentprovider/*  *  一個能匹配person表中任意一行的Uri可以寫成:  *  content://cn.bs.testcontentprovider/person/#  *   */ public class ContentProviderTest extends ContentProvider {   private SQLiteDatabaseOpenHelper mSQLiteDatabaseOpenHelper;   private final static String AUTHORITY="cn.bs.testcontentprovider";   private static UriMatcher mUriMatcher;   private static final int PERSON_DIR = 0;   private static final int PERSON = 1;      /**    * 利用靜態(tài)代碼塊初始化UriMatcher    * 在UriMatcher中包含了多個Uri,每個Uri代表一種操作    * 當(dāng)調(diào)用UriMatcher.match(Uri uri)方法時就會返回該uri對應(yīng)的code;    * 比如此處的PERSONS和PERSON    */   static {     mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);     // 該URI表示返回所有的person,其中PERSONS為該特定Uri的標(biāo)識碼     mUriMatcher.addURI(AUTHORITY, "person", PERSON_DIR);     // 該URI表示返回某一個person,其中PERSON為該特定Uri的標(biāo)識碼     mUriMatcher.addURI(AUTHORITY, "person/#", PERSON);   }         /**    * 在自定義ContentProvider中必須覆寫getType(Uri uri)方法.    * 該方法用于獲取Uri對象所對應(yīng)的MIME類型.    *    * 一個Uri對應(yīng)的MIME字符串遵守以下三點(diǎn):    * 1 必須以vnd開頭    * 2 如果該Uri對應(yīng)的數(shù)據(jù)可能包含多條記錄,那么返回字符串應(yīng)該以"vnd.android.cursor.dir/"開頭    * 3 如果該Uri對應(yīng)的數(shù)據(jù)只包含一條記錄,那么返回字符串應(yīng)該以"vnd.android.cursor.item/"開頭    */   @Override   public String getType(Uri uri) {     switch (mUriMatcher.match(uri)) {     case PERSON_DIR:       return "vnd.android.cursor.dir/"+AUTHORITY+".persons";     case PERSON:       return "vnd.android.cursor.item/"+AUTHORITY+".person";     default:       throw new IllegalArgumentException("unknown uri"+uri.toString());     }   }         @Override   public boolean onCreate() {     mSQLiteDatabaseOpenHelper=new SQLiteDatabaseOpenHelper(getContext());     return true;   }       /**    * 插入操作:    * 插入操作只有一種可能:向一張表中插入    * 返回結(jié)果為新增記錄對應(yīng)的Uri    * 方法db.insert()返回結(jié)果為新增記錄對應(yīng)的主鍵值    */   @Override   public Uri insert(Uri uri, ContentValues values) {     SQLiteDatabase db = mSQLiteDatabaseOpenHelper.getWritableDatabase();     switch (mUriMatcher.match(uri)) {     case PERSON_DIR:       long newId = db.insert("person", "name,phone,salary", values);       //向外界通知該ContentProvider里的數(shù)據(jù)發(fā)生了變化 ,以便ContentObserver作出相應(yīng)        getContext().getContentResolver().notifyChange(uri, null);        return ContentUris.withAppendedId(uri, newId);     default:       throw new IllegalArgumentException("unknown uri" + uri.toString());     }   }      /**    * 更新操作:    * 更新操作有兩種可能:更新一張表或者更新某條數(shù)據(jù)    * 在更新某條數(shù)據(jù)時原理類似于查詢某條數(shù)據(jù),見下.    */   @Override   public int update(Uri uri, ContentValues values, String selection,String[] selectionArgs) {     SQLiteDatabase db = mSQLiteDatabaseOpenHelper.getWritableDatabase();     int updatedNum = 0;     switch (mUriMatcher.match(uri)) {     // 更新表     case PERSON_DIR:       updatedNum = db.update("person", values, selection, selectionArgs);       break;     // 按照id更新某條數(shù)據(jù)     case PERSON:       long id = ContentUris.parseId(uri);       String where = "personid=" + id;       if (selection != null && !"".equals(selection.trim())) {         where = selection + " and " + where;       }       updatedNum = db.update("person", values, where, selectionArgs);       break;     default:       throw new IllegalArgumentException("unknown uri" + uri.toString());     }     //向外界通知該ContentProvider里的數(shù)據(jù)發(fā)生了變化 ,以便ContentObserver作出相應(yīng)      getContext().getContentResolver().notifyChange(uri, null);      return updatedNum;   }      /**    * 刪除操作:    * 刪除操作有兩種可能:刪除一張表或者刪除某條數(shù)據(jù)    * 在刪除某條數(shù)據(jù)時原理類似于查詢某條數(shù)據(jù),見下.    */   @Override   public int delete(Uri uri, String selection, String[] selectionArgs) {     SQLiteDatabase db = mSQLiteDatabaseOpenHelper.getWritableDatabase();     int deletedNum = 0;     switch (mUriMatcher.match(uri)) {     // 刪除表     case PERSON_DIR:       deletedNum = db.delete("person", selection, selectionArgs);       break;     // 按照id刪除某條數(shù)據(jù)     case PERSON:       long id = ContentUris.parseId(uri);       String where = "personid=" + id;       if (selection != null && !"".equals(selection.trim())) {         where = selection + " and " + where;       }       deletedNum = db.delete("person", where, selectionArgs);       break;     default:       throw new IllegalArgumentException("unknown uri" + uri.toString());     }     //向外界通知該ContentProvider里的數(shù)據(jù)發(fā)生了變化 ,以便ContentObserver作出相應(yīng)      getContext().getContentResolver().notifyChange(uri, null);      return deletedNum;   }    /**    * 查詢操作:    * 查詢操作有兩種可能:查詢一張表或者查詢某條數(shù)據(jù)    *    * 注意事項(xiàng):    * 在查詢某條數(shù)據(jù)時要注意--因?yàn)榇颂幨前凑誴ersonid來查詢    * 某條數(shù)據(jù),但是同時可能還有其他限制.例如:    * 要求personid為2且name為xiaoming1    * 所以在查詢時分為兩步:    * 第一步:    * 解析出personid放入where查詢條件    * 第二步:    * 判斷是否有其他限制(如name),若有則將其組拼到where查詢條件.    *    * 詳細(xì)代碼見下.    */   @Override   public Cursor query(Uri uri, String[] projection, String selection,String[] selectionArgs, String sortOrder) {     SQLiteDatabase db = mSQLiteDatabaseOpenHelper.getWritableDatabase();     Cursor cursor =null;     switch (mUriMatcher.match(uri)) {     // 查詢表     case PERSON_DIR:       cursor = db.query("person", projection, selection, selectionArgs,null, null, sortOrder);       break;     // 按照id查詢某條數(shù)據(jù)     case PERSON:       // 第一步:       long id = ContentUris.parseId(uri);       String where = "personid=" + id;       // 第二步:       if (selection != null && !"".equals(selection.trim())) {         where = selection + " and " + where;       }       cursor = db.query("person", projection, where, selectionArgs, null, null, sortOrder);       break;     default:       throw new IllegalArgumentException("unknown uri" + uri.toString());     }     return cursor;   }     } 

SQLiteDatabaseOpenHelper如下:

package cn.testcontentprovider; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; public class SQLiteDatabaseOpenHelper extends SQLiteOpenHelper {   public SQLiteDatabaseOpenHelper(Context context) {     super(context, "contentprovidertest.db", null, 1);   }    @Override   public void onCreate(SQLiteDatabase db) {     db.execSQL("create table person(personid integer primary key autoincrement,name varchar(20),phone varchar(12),salary Integer(12))");       }    //當(dāng)數(shù)據(jù)庫版本號發(fā)生變化時調(diào)用該方法   @Override   public void onUpgrade(SQLiteDatabase db, int arg1, int arg2) {     //db.execSQL("ALTER TABLE person ADD phone varchar(12) NULL");     //db.execSQL("ALTER TABLE person ADD salary Integer NULL");   }  } MainActivity如下:[java] view plain copypackage cn.testcontentprovider; import android.app.Activity; import android.os.Bundle; public class MainActivity extends Activity {   @Override   protected void onCreate(Bundle savedInstanceState) {     super.onCreate(savedInstanceState);     setContentView(R.layout.main);   }  } 

AndroidManifest.xml如下:

<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android"   package="cn.testcontentprovider"   android:versionCode="1"   android:versionName="1.0" >    <uses-sdk     android:minSdkVersion="8"     android:targetSdkVersion="8" />    <uses-permission android:name="android.permission.INTERNET" />   <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />   <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />   <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />      <application     android:allowBackup="true"     android:icon="@drawable/ic_launcher"     android:label="@string/app_name"     android:theme="@style/AppTheme" >     <activity       android:name="cn.testcontentprovider.MainActivity"       android:label="@string/app_name" >       <intent-filter>         <action android:name="android.intent.action.MAIN" />          <category android:name="android.intent.category.LAUNCHER" />       </intent-filter>     </activity>           <provider        android:name="cn.testcontentprovider.ContentProviderTest"       android:authorities="cn.bs.testcontentprovider"       android:exported="true"      />   </application>  </manifest> 

main.xml如下:

<RelativeLayout    xmlns:android="http://schemas.android.com/apk/res/android"   xmlns:tools="http://schemas.android.com/tools"   android:layout_width="match_parent"   android:layout_height="match_parent"   >     <Button     android:layout_width="wrap_content"     android:layout_height="wrap_content"     android:text="該應(yīng)用包含一個自定義的ContentProvider"     android:textSize="15sp"    android:layout_centerInParent="true"   />  </RelativeLayout> 

以下代碼為工程TestBaidu

MainActivity如下:

package cn.testbaidu; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.app.Activity; import android.content.ContentResolver; import android.content.ContentValues; import android.database.ContentObserver; import android.database.Cursor; /**  * Demo描述:  * 應(yīng)用A(TestBaidu)調(diào)用另外一個應(yīng)用(TestContentProvider)中的自定義ContentProvider,即:  * 1 自定義ContentProvider的使用  * 2 其它應(yīng)用調(diào)用該ContentProvider  * 3 ContentObserver的使用  *  * 備注說明:  * 1 該例子在以前版本的基礎(chǔ)上整理了代碼  * 2 該例子在以前版本的基礎(chǔ)上融合了ContentObserver的使用  *  利用ContentObserver隨時監(jiān)聽ContentProvider的數(shù)據(jù)變化.  *  為實(shí)現(xiàn)該功能需要在自定義的ContentProvider的insert(),update(),delete()  *  方法中調(diào)用getContext().getContentResolver().notifyChange(uri, null);  *  向外界通知該ContentProvider里的數(shù)據(jù)發(fā)生了變化 ,以便ContentObserver作出相應(yīng)   *  * 測試方法:  * 1 依次測試ContentProvider的增查刪改(注意該順序)!!  * 2 其它應(yīng)用查詢該ContentProvider的數(shù)據(jù)  *  */ public class MainActivity extends Activity {   private Button mAddButton;   private Button mDeleteButton;   private Button mUpdateButton;   private Button mQueryButton;   private Button mTypeButton;   private long lastTime=0;   private ContentResolver mContentResolver;   private ContentObserverSubClass mContentObserverSubClass;   @Override   protected void onCreate(Bundle savedInstanceState) {     super.onCreate(savedInstanceState);     setContentView(R.layout.main);     init();     initContentObserver();   }    private void init() {     mContentResolver=this.getContentResolver();          mAddButton=(Button) findViewById(R.id.addButton);     mAddButton.setOnClickListener(new ClickListenerImpl());          mDeleteButton=(Button) findViewById(R.id.deleteButton);     mDeleteButton.setOnClickListener(new ClickListenerImpl());          mUpdateButton=(Button) findViewById(R.id.updateButton);     mUpdateButton.setOnClickListener(new ClickListenerImpl());          mQueryButton=(Button) findViewById(R.id.queryButton);     mQueryButton.setOnClickListener(new ClickListenerImpl());          mTypeButton=(Button) findViewById(R.id.typeButton);     mTypeButton.setOnClickListener(new ClickListenerImpl());        }          // 注冊一個針對ContentProvider的ContentObserver用來觀察內(nèi)容提供者的數(shù)據(jù)變化   private void initContentObserver() {     Uri uri = Uri.parse("content://cn.bs.testcontentprovider/person");     mContentObserverSubClass=new ContentObserverSubClass(new Handler());     this.getContentResolver().registerContentObserver(uri, true,mContentObserverSubClass);   }      @Override   protected void onDestroy() {     super.onDestroy();     if (mContentObserverSubClass!=null) {       this.getContentResolver().unregisterContentObserver(mContentObserverSubClass);     }   }             // 自定義一個內(nèi)容觀察者ContentObserver   private class ContentObserverSubClass extends ContentObserver {      public ContentObserverSubClass(Handler handler) {       super(handler);     }      //采用時間戳避免多次調(diào)用onChange( )     @Override     public void onChange(boolean selfChange) {       super.onChange(selfChange);       System.out.println("ContentObserver onChange() selfChange="+ selfChange);       if (System.currentTimeMillis()-lastTime>2000) {         ContentResolver resolver = getContentResolver();         Uri uri = Uri.parse("content://cn.bs.testcontentprovider/person");         // 獲取最新的一條數(shù)據(jù)         Cursor cursor = resolver.query(uri, null, null, null,"personid desc limit 1");         while (cursor.moveToNext()) {           int personid = cursor.getInt(cursor.getColumnIndex("personid"));           System.out.println("內(nèi)容提供者中的數(shù)據(jù)發(fā)生變化,現(xiàn)數(shù)據(jù)中第一條數(shù)據(jù)的personid="+ personid);         }         cursor.close();         lastTime=System.currentTimeMillis();       }else{         System.out.println("時間間隔過短,忽略此次更新");       }                   }          @Override     public boolean deliverSelfNotifications() {       return true;     }        }                private class ClickListenerImpl implements OnClickListener {     @Override     public void onClick(View v) {       switch (v.getId()) {       case R.id.addButton:         Person person = null;         for (int i = 0; i < 5; i++) {           person = new Person("xiaoming" + i, "9527" + i, (8888 + i));           testInsert(person);         }         break;       case R.id.deleteButton:         testDelete(1);         break;       case R.id.updateButton:         testUpdate(3);         break;       case R.id.queryButton:         // 查詢表         // queryFromContentProvider(-1);          // 查詢personid=2的數(shù)據(jù)         testQuery(2);         break;       case R.id.typeButton:         testType();         break;       default:         break;       }      }    }   private void testInsert(Person person) {     ContentValues contentValues=new ContentValues();     contentValues.put("name", person.getName());     contentValues.put("phone", person.getPhone());     contentValues.put("salary",person.getSalary());     Uri insertUri=Uri.parse("content://cn.bs.testcontentprovider/person");     Uri returnUri=mContentResolver.insert(insertUri, contentValues);     System.out.println("新增數(shù)據(jù):returnUri="+returnUri);   }      private void testDelete(int index){     Uri uri=Uri.parse("content://cn.bs.testcontentprovider/person/"+String.valueOf(index));     mContentResolver.delete(uri, null, null);   }      private void testUpdate(int index){     Uri uri=Uri.parse("content://cn.bs.testcontentprovider/person/"+String.valueOf(index));     ContentValues values=new ContentValues();     values.put("name", "hanmeimei");     values.put("phone", "1234");     values.put("salary", 333);     mContentResolver.update(uri, values, null, null);   }    private void testQuery(int index) {     Uri uri=null;     if (index<=0) {       //查詢表       uri=Uri.parse("content://cn.bs.testcontentprovider/person");     } else {        //按照id查詢某條數(shù)據(jù)       uri=Uri.parse("content://cn.bs.testcontentprovider/person/"+String.valueOf(index));     }          //對應(yīng)上面的:查詢表     //Cursor cursor= mContentResolver.query(uri, null, null, null, null);          //對應(yīng)上面的:查詢personid=2的數(shù)據(jù)     //注意:因?yàn)閚ame是varchar字段的,所以應(yīng)該寫作"name='xiaoming1'"     //   若寫成"name=xiaoming1"查詢時會報錯     Cursor cursor= mContentResolver.query(uri, null, "name='xiaoming1'", null, null);          while(cursor.moveToNext()){       int personid=cursor.getInt(cursor.getColumnIndex("personid"));       String name=cursor.getString(cursor.getColumnIndex("name"));       String phone=cursor.getString(cursor.getColumnIndex("phone"));       int salary=cursor.getInt(cursor.getColumnIndex("salary"));       System.out.println("查詢得到:personid=" + personid+",name="+name+",phone="+phone+",salary="+salary);     }     cursor.close();   }      private void testType(){     Uri dirUri=Uri.parse("content://cn.bs.testcontentprovider/person");     String dirType=mContentResolver.getType(dirUri);     System.out.println("dirType:"+dirType);          Uri itemUri=Uri.parse("content://cn.bs.testcontentprovider/person/3");     String itemType=mContentResolver.getType(itemUri);     System.out.println("itemType:"+itemType);   }  } 

Person如下:

package cn.testbaidu;  public class Person {   private Integer id;   private String name;   private String phone;   private Integer salary;   public Person(String name, String phone,Integer salary) {     this.name = name;     this.phone = phone;     this.salary=salary;   }   public Person(Integer id, String name, String phone,Integer salary) {     this.id = id;     this.name = name;     this.phone = phone;     this.salary=salary;   }   public Integer getId() {     return id;   }   public void setId(Integer id) {     this.id = id;   }   public String getName() {     return name;   }   public void setName(String name) {     this.name = name;   }   public String getPhone() {     return phone;   }   public void setPhone(String phone) {     this.phone = phone;   }   public Integer getSalary() {     return salary;   }   public void setSalary(Integer salary) {     this.salary = salary;   }   @Override   public String toString() {     return "Person [id=" + id + ", name=" + name + ", phone=" + phone+ ", salary=" + salary + "]";   }          } 

main.xml如下:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"   xmlns:tools="http://schemas.android.com/tools"   android:layout_width="match_parent"   android:layout_height="match_parent" >    <Button     android:id="@+id/addButton"     android:layout_width="wrap_content"     android:layout_height="wrap_content"     android:layout_centerHorizontal="true"     android:layout_marginTop="30dip"     android:text="增加"     android:textSize="20sp" />       <Button     android:id="@+id/queryButton"     android:layout_width="wrap_content"     android:layout_height="wrap_content"     android:layout_centerHorizontal="true"     android:layout_marginTop="30dip"      android:layout_below="@id/addButton"     android:text="查詢"     android:textSize="20sp" />       <Button     android:id="@+id/deleteButton"     android:layout_width="wrap_content"     android:layout_height="wrap_content"     android:layout_centerHorizontal="true"     android:layout_marginTop="30dip"     android:layout_below="@id/queryButton"     android:text="刪除"     android:textSize="20sp" />    <Button     android:id="@+id/updateButton"     android:layout_width="wrap_content"     android:layout_height="wrap_content"     android:layout_centerHorizontal="true"     android:layout_marginTop="30dip"      android:layout_below="@id/deleteButton"     android:text="修改"     android:textSize="20sp" />       <Button     android:id="@+id/typeButton"     android:layout_width="wrap_content"     android:layout_height="wrap_content"     android:layout_centerHorizontal="true"     android:layout_marginTop="30dip"      android:layout_below="@id/updateButton"     android:text="類型"     android:textSize="20sp" />  </RelativeLayout> 

如有疑問請留言或者到本站社區(qū)交流討論,感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!


注:相關(guān)教程知識閱讀請移步到Android開發(fā)頻道。
發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 武义县| 沛县| 吉林省| 迭部县| 新和县| 金坛市| 富川| 商都县| 辉县市| 桐庐县| 循化| 呼图壁县| 琼结县| 康保县| 汪清县| 鹤庆县| 咸阳市| 嘉禾县| 惠安县| 平遥县| 眉山市| 祁连县| 监利县| 江西省| 白河县| 黎川县| 承德市| 浦东新区| 曲麻莱县| 宿松县| 汝州市| 屏南县| 台山市| 美姑县| 当雄县| 古丈县| 安福县| 合江县| 洛阳市| 巴中市| 伊吾县|