Android学习之路--四大组件--ContentProvider

来源:互联网 发布:淘宝直通车助手 编辑:程序博客网 时间:2024/05/29 05:06

四大组件

  • Activity
  • BroadCastReceiver
  • Service
  • ContentProvider

· ContentProvider

        按照谷歌API给的说法,ContentProvider其实就是一个数据共享的一个东西,它是为多个应用提供数据共享的唯一一种方式。比如电话本,电话本数据可以为多个应用提供数据,它就是ContentProvider实现的。如果你的应用不想为其他应用提供数据共享,那么你就可以用手机SQLiteDataBase实现。

       当进行数据共享时,一个请求通过ContentResolver系统检查特定URI认证,并将请求内容提供者注册的认证。内容提供者可以解释它想要的URI。我们用UriMatcher类来管理URL。
       在运用ContentProvider时,我们要实现以下几个方法:

  • onCreate() : ContentProvider初始化调用
  • query(Uri, String[], String, String[], String) : 将结果返回给调用者
  • insert(Uri, ContentValues) : 向ContentProvider插入一条数据
  • update(Uri, ContentValues, String, String[]) : ContentProvider更新一条数据
  • delete(Uri, String, String[]) : ContentProvider删除一条数据
  • getType(Uri) : 给ContentProvider返回一个MIME数据类型

注意 :
       ContentProvider中的query 和 update方法在同一时间有几个线程调用时,那么必须是线程安全的。其他的方法也必须值UI线程中调用,否则会报错。

好了,我们结合一个简单的程序实例来具体说下。


       1、首先我们自定义我们自己的ContentProvider,直接继承自ContentProvider即可。

public class TestContentProvider extends ContentProvider {    private TestMyDatabase myDatabase;    private SQLiteDatabase dbHelper;    static UriMatcher uriMatcher;    static {        uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);        uriMatcher.addURI("zhulinxianzi.com", "first", 1);        uriMatcher.addURI("zhulinxianzi.com", "first/#", 2);        uriMatcher.addURI("zhulinxianzi.com", "first/*", 3);        uriMatcher.addURI("zhulinxianzi.com", "second", 4);        uriMatcher.addURI("zhulinxianzi.com", "second/#", 5);        uriMatcher.addURI("zhulinxianzi.com", "second/*", 6);    }    @Override    public boolean onCreate() {        if (myDatabase == null) {            myDatabase = new TestMyDatabase(App.appContext);        }        return true;    }    @Nullable    @Override    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {        dbHelper = myDatabase.getWritableDatabase();        int code = uriMatcher.match(uri);        Cursor cursor;        SQLiteQueryBuilder builder = new SQLiteQueryBuilder();        switch (code) {            case 1:                builder.setTables(TestMyDatabase.TABLE_NAME);                break;            case 2:                builder.setTables(TestMyDatabase.TABLE_NAME2);                break;        }        cursor = builder.query(dbHelper, projection,  selection, selectionArgs,null,"",sortOrder);        return cursor;    }    @Nullable    @Override    public String getType(Uri uri) {        return null;    }    @Nullable    @Override    public Uri insert(Uri uri, ContentValues values) {        dbHelper = myDatabase.getWritableDatabase();        int code = uriMatcher.match(uri);        long id;        switch (code) {            case 1:                id = dbHelper.insert(TestMyDatabase.TABLE_NAME, null, values);                break;            case 4:                id = dbHelper.insert(TestMyDatabase.TABLE_NAME2, null, values);                break;            default:                throw new IllegalArgumentException("Unknown URI " + uri);        }        return ContentUris.withAppendedId(uri, id);    }    @Override    public int delete(Uri uri, String selection, String[] selectionArgs) {        return 0;    }    @Override    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {        return 0;    }}

我们在这里稍微说说这个UriMatcher。
UriMatcher我们在初始化的时候都是静态类里初始化。它管理的Uri都是由三部分构成,举个例子:

content://zhulinxianzi.com/first/123content:我们称之为scheme。zhulinxianzi.com:我们称之为:authority。他就是我们进行Uri匹配的重要部分。first/123:我们称之为path。

first部分我们一般取的事数据库表名,在后面的123,我们根据后面的/#还是/*来区分是数字还是任何字符。我们可以更这个来做删除或者更新,其可作为参数使用,比如:

content://zhulinxianzi.com/first/123

long parmas = ContentUris.parseId(uri); 

我们可以得到123这个参数。

content://zhulinxianzi.com/first/lisi

String table = uri.getPathSegments().get(0);String name = uri.getPathSegments().get(1);

table 的值为:first,而name的值为:list 。


2、创建我们我数据库

public class TestMyDatabase extends SQLiteOpenHelper {    public static final String DB_NAME="test.db";    public static final String TABLE_NAME="test";    public static final String TABLE_NAME2="test2";    private static int DB_VERSION= 1;    private static final String CREATE_TABLE = "create table "+TABLE_NAME+" (_id integer primary key autoincrement ,name varchar(30));";    private static final String CREATE_TABLE2 = "create table "+TABLE_NAME2+" (_id integer primary key autoincrement ,name varchar(30));";    public TestMyDatabase(Context context) {        super(context, DB_NAME, null, DB_VERSION);    }    @Override    public void onCreate(SQLiteDatabase db) {        db.execSQL(CREATE_TABLE);        db.execSQL(CREATE_TABLE2);    }    @Override    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {        if(newVersion > oldVersion){            db.execSQL("drop table  if exists "+ TABLE_NAME);            db.execSQL("drop table  if exists "+ TABLE_NAME2);            onCreate(db);        }    }}

3、 manifest里进行配置

<provider    android:authorities="zhulinxianzi.com"    android:name=".control.TestContentProvider"    android:exported="true"/>

exported是第三方是否可以读取数据,值为false,则无法读取,汇报安全权限错误。


4、 接下我我们就可以在自己的应用里或者第三方(有权限)应用调用了。

插入数据:

private void insert() {    ContentResolver cp = getContentResolver();    ContentValues values = new ContentValues();    values.put("name", "liu");    Uri uri = cp.insert(    Uri.parse("content://zhulinxianzi.com/first"), values);    LogUtil.i("info",uri.toString());}

如果插入成功:则日志打印:content://zhulinxianzi.com/first/1。
1是代表插入成功后数据库返回的当前数据库数据的id号。

查询数据:

private void getCount(){     ContentResolver cp= getContentResolver();         Cursor cursor = cp.query(                Uri.parse("content://zhulinxizi.com/first"),                null,null,null,null);         if (cursor!= null) {             Log.i("info","cursor.size :" + cursor.getCount());         }         ···· }

查询成功后,会打印数据的条数,显示数据等操作。

至于其他的我们删除、更新都是同样的做法,不在赘述。


我们在这里的方法getType是返回的null。这个一般用的少,但是从谷歌官方解释说,它是返回uri里对应的MIME值。如果是一条数据,那么它返回的应该是vnd.android.cursor.item开头,如果是数据集多条数据的话,应该是以vnd.android.cursor.dir/开头,/后面的我们可以随便写了。另外,这也可以用在第三方获取数据的读写权限和隐式调用中。

在manifest配置provider时,我们看到还可以配置其他的具体权限问题:

 <provider     android:authorities="wanduoduo.com"     android:name=".control.TestContentProvider"     android:exported="true"     android:permission=""     android:readPermission=""     android:writePermission=""     />

具体的权限问题和getType的问题,大家可以上网自行学习下。


       好了,Android四大组件我们介绍完了。接下来,我们进入View的重头戏吧。
祝大家2017年生活幸福,快乐每一天。

1 0
原创粉丝点击