Android学习之路--四大组件--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/123
content:我们称之为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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值