zoukankan      html  css  js  c++  java
  • Android开发之ContentProvider的简单使用

    ContentProvider,内容提供者

    官网结构图:

    作为四大组件之一的ContentProvider,主要是用于应用间数据共享使用的。

    ContentProvider把应用的数据封装起来,然后提供一个对外访问的ContentResolver接口。

    假如只是本应用使用的数据,直接通过SQLiteDatabase操作数据库。

    主要原理:一个Uri对象通过ContentResolver请求该应用的数据,ContentProvider解析该Uri并返回给需要的数据。

    实现自定义的ContentProvider,需要继承抽象类android.content.ContentProvider,并实现5个方法:

    onCreate()    初始化provider,返回一个布尔值,创建成功返回一个true

    query(Uri,String[],String,String[],String)   从ContentProvider中查询数据  返回一个Cursor

    insert(Uri,ContentValues)  通过ContentProvider插入新的数据   返回一个Uri

    update(Uri,ContentValues,String,String[])   通过ContentProvider更新数据   返回一个int

    delete(Uri,String,String[])   通过ContentProvider删除数据       返回一个int

    getType(Uri)   根据传入的Uri,返回相应的MIME类型。  返回一个String

    Uri类

    一个Uri有三部分组成:Scheme+Authority+Path

    1.scheme, contentprovider为content://

    2.Authority,一般使用应用的包名,如com.example.appone或者也可以这样com.example.appone.provider

    3.Path,即提供对外访问的table,如访问表table,写成/table

    上面的Uri可以写成这样:content://com.example.appone.provider/table

    一个字符串通过Uri类中的parse()方法可以转换为Uri对象,如下:

    1 Uri uri=Uri.parse("content://com.example.appone.provider/table");

    UriMatcher类,ContentUris类contentResolver类

    UriMather类用于匹配uri,用法如下:

     1     private static final int PEOPLE = 1;
     2     private static final int PEOPLE_ID = 2;
     3     private static final int PEOPLE_PHONES = 3;
     4     private static final int PEOPLE_PHONES_ID = 4;
     5     private static final int PEOPLE_CONTACTMETHODS = 7;
     6     private static final int PEOPLE_CONTACTMETHODS_ID = 8;
     7 
     8     private static final int DELETED_PEOPLE = 20;
     9 
    10     private static final int PHONES = 9;
    11     private static final int PHONES_ID = 10;
    12     private static final int PHONES_FILTER = 14;
    13 
    14     private static final int CONTACTMETHODS = 18;
    15     private static final int CONTACTMETHODS_ID = 19;
    16 
    17     private static final int CALLS = 11;
    18     private static final int CALLS_ID = 12;
    19     private static final int CALLS_FILTER = 15;
    20 
    21     private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH); //常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码(-1)
    22 
    23     static
    24     {
    25         sURIMatcher.addURI("contacts", "people", PEOPLE); //如果match()方法匹配,返回匹配码为1
    26         sURIMatcher.addURI("contacts", "people/#", PEOPLE_ID);    //如果match()方法匹配,返回匹配码为2
    27         sURIMatcher.addURI("contacts", "people/#/phones", PEOPLE_PHONES);
    28         sURIMatcher.addURI("contacts", "people/#/phones/#", PEOPLE_PHONES_ID);
    29         sURIMatcher.addURI("contacts", "people/#/contact_methods", PEOPLE_CONTACTMETHODS);
    30         sURIMatcher.addURI("contacts", "people/#/contact_methods/#", PEOPLE_CONTACTMETHODS_ID);
    31         sURIMatcher.addURI("contacts", "deleted_people", DELETED_PEOPLE);
    32         sURIMatcher.addURI("contacts", "phones", PHONES);
    33         sURIMatcher.addURI("contacts", "phones/filter/*", PHONES_FILTER);
    34         sURIMatcher.addURI("contacts", "phones/#", PHONES_ID);
    35         sURIMatcher.addURI("contacts", "contact_methods", CONTACTMETHODS);
    36         sURIMatcher.addURI("contacts", "contact_methods/#", CONTACTMETHODS_ID);
    37         sURIMatcher.addURI("call_log", "calls", CALLS);
    38         sURIMatcher.addURI("call_log", "calls/filter/*", CALLS_FILTER);
    39         sURIMatcher.addURI("call_log", "calls/#", CALLS_ID);
    40     }

    从API:18开始,路径可以用一个斜线开始。 例如:

    1 sURIMatcher.addURI("contacts", "/people", PEOPLE);

    注册完需要匹配的Uri后,在getType()方法中可以使用sURIMatcher.match(uri)方法对输入的Uri进行匹配,如果匹配成功就返回匹配码,匹配码是调用addURI()方法传入的第三个参数。

     1     public String getType(Uri url)
     2     {
     3         int match = sURIMatcher.match(url);
     4         switch (match)
     5         {
     6             case PEOPLE:
     7                 return "vnd.android.cursor.dir/person";
     8             case PEOPLE_ID:
     9                 return "vnd.android.cursor.item/person";
    10 ... snip ...
    11                 return "vnd.android.cursor.dir/snail-mail";
    12             case PEOPLE_ADDRESS_ID:
    13                 return "vnd.android.cursor.item/snail-mail";
    14             default:
    15                 return null;
    16         }
    17     }

    ContentUris类,用于获取Uri路径后面的ID部分,它有两个比较实用的方法:

        withAppendedId(uri, id)用于为路径加上ID部分

    1 Uri uri = Uri.parse("content://com.ljq.provider.personprovider/person")
    2 Uri resultUri = ContentUris.withAppendedId(uri, 10); 
    3 //生成后的Uri为:content://com.ljq.provider.personprovider/person/10

        parseId(uri)方法用于从路径中获取ID部分

    1 Uri uri = Uri.parse("content://com.ljq.provider.personprovider/person/10")
    2 long personid = ContentUris.parseId(uri);//获取的结果为:10

    ContentResolver类,当外部应用需要对ContentProvider的数据库进行CRUD时,可以使用ContentResolver类来完成。获取ContentResolver对象,可以通过Content的getContentResolver()方法获取到。ContentResolver使用insert()、delete()、update()、query()方法,来操作数据。

    实现了一个Demo,代码如下:

    1.工具类:Xin类

     1 package com.example.appone;
     2 
     3 public class Xin {
     4 
     5     public static final String DBNAME = "xinonlinedb";
     6     public static final String TNAME = "xinonline";
     7     public static final int VERSION = 3;
     8 
     9     public static String TID = "tid";
    10     public static final String EMAIL = "email";
    11     public static final String USERNAME = "username";
    12     public static final String DATE = "date";
    13     public static final String SEX = "sex";
    14 
    15     public static final String AUTOHORITY = "com.example.appone.provider";
    16     public static final int ITEM = 1;
    17     public static final int ITEM_ID = 2;
    18 
    19     public static final String CONTENT_TYPE = "vnd.android.cursor.dir";
    20     public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item";
    21 
    22 }

    2.创建数据库:DBlite类

     1 package com.example.appone;
     2 
     3 import android.content.Context;
     4 import android.database.sqlite.SQLiteDatabase;
     5 import android.database.sqlite.SQLiteDatabase.CursorFactory;
     6 import android.database.sqlite.SQLiteOpenHelper;
     7 
     8 public class DBlite extends SQLiteOpenHelper {
     9 
    10     public DBlite(Context context, String name, CursorFactory factory,
    11             int version) {
    12         super(context, name, factory, version);
    13 
    14     }
    15 
    16     @Override
    17     public void onCreate(SQLiteDatabase db) {
    18         db.execSQL("CREATE TABLE " + Xin.TNAME + "(" + Xin.TID
    19                 + " integer primary key autoincrement not null," + Xin.EMAIL
    20                 + " text not null, " + Xin.USERNAME + " text not null,"
    21                 + Xin.DATE + " text not null, " + Xin.SEX + " text not null);");
    22     }
    23 
    24     @Override
    25     public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    26 
    27     }
    28 
    29 }

    3.创建自定义的ContentProvider,对数据库进行包装:MyProvider类

      1 package com.example.appone;
      2 
      3 import android.content.ContentProvider;
      4 import android.content.ContentValues;
      5 import android.content.UriMatcher;
      6 import android.database.Cursor;
      7 import android.database.sqlite.SQLiteDatabase;
      8 import android.net.Uri;
      9 
     10 public class MyProvider extends ContentProvider {
     11 
     12     private DBlite dBlite;
     13     private SQLiteDatabase db;
     14     private Cursor cursor;
     15 
     16     private static final UriMatcher sMatcher;
     17     static {
     18         sMatcher = new UriMatcher(UriMatcher.NO_MATCH);
     19         sMatcher.addURI(Xin.AUTOHORITY, Xin.TNAME, Xin.ITEM);
     20         sMatcher.addURI(Xin.AUTOHORITY, Xin.TNAME + "/#", Xin.ITEM_ID);
     21 
     22     }
     23 
     24     @Override
     25     public boolean onCreate() {
     26         dBlite = new DBlite(getContext(), Xin.DBNAME, null, Xin.VERSION);
     27         return true;
     28 
     29     }
     30 
     31     @Override
     32     public Cursor query(Uri uri, String[] projection, String selection,
     33             String[] selectionArgs, String sortOrder) {
     34         db = dBlite.getWritableDatabase();
     35         switch (sMatcher.match(uri)) {
     36         case Xin.ITEM:
     37             cursor = db.query(Xin.TNAME, projection, selection, selectionArgs,
     38                     null, null, sortOrder);
     39             break;
     40         case Xin.ITEM_ID:
     41             String id = uri.getPathSegments().get(1);
     42             cursor = db.query(Xin.TNAME, projection, "tid=?",
     43                     new String[] { id }, null, null, sortOrder);
     44             break;
     45 
     46         default:
     47             break;
     48         }
     49         return cursor;
     50     }
     51 
     52     @Override
     53     public Uri insert(Uri uri, ContentValues values) {
     54         db = dBlite.getWritableDatabase();
     55         long returnId = db.insert(Xin.TNAME, null, values);
     56         Uri uriReturn = Uri.parse("content://" + Xin.AUTOHORITY + "/"
     57                 + Xin.TNAME + "/" + returnId);
     58 
     59         return uriReturn;
     60     }
     61 
     62     @Override
     63     public int delete(Uri uri, String selection, String[] selectionArgs) {
     64         db = dBlite.getWritableDatabase();
     65         int deleteId = 0;
     66         switch (sMatcher.match(uri)) {
     67         case Xin.ITEM:
     68             deleteId = db.delete(Xin.TNAME, selection, selectionArgs);
     69 
     70             break;
     71         case Xin.ITEM_ID:
     72             String id = uri.getPathSegments().get(1);
     73             deleteId = db.delete(Xin.TNAME, "tid=?", new String[] { id });
     74 
     75         default:
     76             break;
     77         }
     78         return deleteId;
     79     }
     80 
     81     @Override
     82     public int update(Uri uri, ContentValues values, String selection,
     83             String[] selectionArgs) {
     84         db = dBlite.getWritableDatabase();
     85         int updateId = 0;
     86         switch (sMatcher.match(uri)) {
     87         case Xin.ITEM:
     88             updateId = db.update(Xin.TNAME, values, selection, selectionArgs);
     89             break;
     90         case Xin.ITEM_ID:
     91             String id = uri.getPathSegments().get(1);
     92             updateId = db.update(Xin.TNAME, values, "tid= ?",
     93                     new String[] { id });
     94             break;
     95 
     96         default:
     97             break;
     98         }
     99         return updateId;
    100     }
    101 
    102     @Override
    103     public String getType(Uri uri) {
    104         switch (sMatcher.match(uri)) {
    105         case Xin.ITEM:
    106             return Xin.CONTENT_TYPE + "/vnd." + Xin.AUTOHORITY + Xin.TNAME;
    107         case Xin.ITEM_ID:
    108             return Xin.CONTENT_ITEM_TYPE + "/vnd." + Xin.AUTOHORITY + Xin.TNAME;
    109 
    110         }
    111         return null;
    112     }
    113 
    114 }

    4.在manifest文件中对MyProvider进行注册

     1 <?xml version="1.0" encoding="utf-8"?>
     2 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     3     package="com.example.appone"
     4     android:versionCode="1"
     5     android:versionName="1.0" >
     6 
     7     <uses-sdk
     8         android:minSdkVersion="14"
     9         android:targetSdkVersion="21" />
    10 
    11     <application
    12         android:allowBackup="true"
    13         android:icon="@drawable/ic_launcher"
    14         android:label="@string/app_name"
    15         android:theme="@style/AppTheme" >
    16         <activity
    17             android:name=".MainActivity"
    18             android:label="@string/app_name" >
    19             <intent-filter>
    20                 <action android:name="android.intent.action.MAIN" />
    21 
    22                 <category android:name="android.intent.category.LAUNCHER" />
    23             </intent-filter>
    24         </activity>
    25 
    26         <provider
    27             android:name="com.example.appone.MyProvider"
    28             android:authorities="com.example.appone.provider"
    29             android:exported="true" >
    30         </provider>
    31     </application>
    32 
    33 </manifest>

    5.在MainActivity中使用ContentProvider进行CRUD

     1 package com.example.appone;
     2 
     3 import android.app.Activity;
     4 import android.content.ContentValues;
     5 import android.database.Cursor;
     6 import android.net.Uri;
     7 import android.os.Bundle;
     8 import android.util.Log;
     9 import android.view.View;
    10 import android.view.View.OnClickListener;
    11 import android.view.Window;
    12 
    13 public class MainActivity extends Activity implements OnClickListener {
    14 
    15     private String newid;
    16 
    17     @Override
    18     protected void onCreate(Bundle savedInstanceState) {
    19         super.onCreate(savedInstanceState);
    20         requestWindowFeature(Window.FEATURE_NO_TITLE);
    21         setContentView(R.layout.activity_contentprovider);
    22 
    23         findViewById(R.id.contentProvider_query).setOnClickListener(this);
    24         findViewById(R.id.contentProvider_insert).setOnClickListener(this);
    25         findViewById(R.id.contentProvider_update).setOnClickListener(this);
    26         findViewById(R.id.contentProvider_delete).setOnClickListener(this);
    27     }
    28 
    29     @Override
    30     public void onClick(View v) {
    31         Uri uriItem = Uri.parse("content://"+Xin.AUTOHORITY+"/"+Xin.TNAME);
    32         Uri uriId = Uri.parse("content://"+Xin.AUTOHORITY+"/"+Xin.TNAME+"/"+newid);
    33         switch (v.getId()) {
    34         case R.id.contentProvider_query:
    35             Cursor cursor=this.getContentResolver().query(uriItem, null, null, null, null);
    36             if (cursor!=null) {
    37                 while (cursor.moveToNext()) {
    38                     String userName=cursor.getString(cursor.getColumnIndex(Xin.USERNAME));
    39                     String sex = cursor.getString(cursor.getColumnIndex(Xin.SEX));
    40                     String email = cursor.getString(cursor.getColumnIndex(Xin.EMAIL));
    41                     String date = cursor.getString(cursor.getColumnIndex(Xin.DATE));
    42                     Log.e("appone", "获取到的信息为:"+userName+email+date+sex);
    43                 }
    44                 cursor.close();
    45             }
    46             break;
    47             
    48         case R.id.contentProvider_insert:
    49             ContentValues values = new ContentValues();
    50             values.put(Xin.EMAIL, "1234@12.com");
    51             values.put(Xin.USERNAME, "张三");
    52             values.put(Xin.DATE, "2015");
    53             values.put(Xin.SEX, "男");
    54             Uri newUri = this.getContentResolver().insert(uriItem,values);
    55             newid = newUri.getPathSegments().get(1);
    56             break;
    57             
    58         case R.id.contentProvider_update:
    59             ContentValues values2= new ContentValues();
    60             values2.put(Xin.USERNAME, "王五");
    61             values2.put(Xin.EMAIL, "xxx@ddd.com");
    62             values2.put(Xin.SEX, "女");
    63             this.getContentResolver().update(uriId, values2, null, null);
    64             break;
    65             
    66         case R.id.contentProvider_delete:
    67             this.getContentResolver().delete(uriId, null, null);
    68             break;
    69 
    70         default:
    71             break;
    72         }
    73     }
    74 
    75 }

    注意:

    首先需要插入消息,然后再查询或者更新或者删除,否则newId的值为空。

  • 相关阅读:
    国际标准:ISO 8601
    Python中文问题SyntaxError
    主人与狗
    三星Galaxy note I9220 N7000 刷机ROOT工具及ROM下载
    电子书下载:Pro ASP.NET 4 in C# 2010
    Rad Studio IDE 代码编辑器增强工具 RADSplit
    电子书下载:Essential Windows Phone 7.5
    3D成像法:抖动
    减小delphi生成EXE文件体积的方法
    unisynedit 在Delphi 2010下的编译问题
  • 原文地址:https://www.cnblogs.com/liyiran/p/4953632.html
Copyright © 2011-2022 走看看