欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

《Android开发艺术探索》阅读笔记(七)

程序员文章站 2024-03-26 11:40:59
...

4.5 使用ContentProvider:

本篇是介绍如何使用ContentProvider的案例,客户端通过访问ContentProvider,对数据库进行操作。

第一步,创建数据库:
构造函数里创建数据库,在onCreate()中创建表(使用SQL语句)

public class DbOpenHelper extends SQLiteOpenHelper {

    private static final String DB_NAME = "book_provider.db";
    
    public static final String BOOK_TABLE_NAME = "book";
    public static final String USER_TABLE_NAME = "user";

    private static final int DB_VERSION = 2;

    //创建表的语句,包括表的名称、表内的数据项
    private String CREATE_BOOK_TABLE = "CREATE TABLE IF NOT EXISTS "
            + BOOK_TABLE_NAME + "(_id INTEGER PRIMARY KEY," + "name TEXT)";

    private String CREATE_USER_TABLE = "CREATE TABLE IF NOT EXISTS "
            + USER_TABLE_NAME + "(_id INTEGER PRIMARY KEY," + "name TEXT," + "sex INT)";

    //构造函数,创建database
    public DbOpenHelper(Context context){
        super(context,DB_NAME,null,DB_VERSION);
    }

    //执行语句创建book表、user表
    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(CREATE_BOOK_TABLE);
        db.execSQL(CREATE_USER_TABLE);
    }

    //更新数据库
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        //TODO ignored
    }
}

第二步,创建ContentProvider:
ContentProvider里,用new DbOpenHelper(Context).getWritableDatabase()DbOpenHelper类获取SQLiteDatabase实例,然后对此SQLiteDatabase实例进行操作。

重写的六个抽象方法:onCreate代表ContentProvider的创建,getType用来返回一个Uri请求所对应的MIME类型(媒体类型,图片,视频等),queryupdateinsertdelete实现数据表的增删改查功能。
(onCreate运行在主线程里,其余五个运行在Binder线程池中)

public class BookProvider extends ContentProvider {

    //Log标签
    private static final String TAG  = "aa20190131";

    //ContentProvider的唯一标识符
    public static final String AUTHORITY = "com.example.a20190130.BookProvider11";

    //Uri_Code,用于帮助getTableName()识别
    public static final int BOOK_URI_CODE = 0;
    public static final int USER_URI_CODE = 1;

    //UriMatcher很重要,它将客户端传过来的Uri转换为其他可识别的标志
    private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);

    private Context mContext;
    private SQLiteDatabase mDb;

    //将Uri和的Uri_Code相关联
    static {
        sUriMatcher.addURI(AUTHORITY,"book",BOOK_URI_CODE);
        sUriMatcher.addURI(AUTHORITY,"user",USER_URI_CODE);
    }

    //初始化
    @Override
    public boolean onCreate() {
        Log.d(TAG,"onCreate, current thread:" + Thread.currentThread().getName());
        mContext = getContext();
        //onCreate()在主线程中运行,实际使用中不推荐进行耗时的数据库操作
        initProviderData();//初始化数据表
        return true;
    }

    //客户端执行query时会跳到这里
    @Override
    public Cursor query(Uri uri,String[] projection,String selection, String[] selectionArgs, String sortOrder) {
        Log.d(TAG,"query, current thread:" + Thread.currentThread().getName());
        String table = getTableName(uri);
        if (table == null){
            throw new IllegalArgumentException("Unsupported URI:" + uri);
        }
        return mDb.query(table,projection,selection,selectionArgs,null,null,sortOrder,null);
    }

    @Override
    public String getType(Uri uri) {
        Log.d(TAG,"getType");
        return null;
    }

    //客户端执行insert时会跳到这里
    @Override
    public Uri insert(Uri uri,ContentValues values) {
        Log.d(TAG,"insert");
        String table = getTableName(uri);
        if (table == null){
            throw new IllegalArgumentException("Unsupport URI:" + uri);
        }
        mDb.insert(table,null,values);
        //通知外界,当前ContentProvider中的数据已经发生改变,不设置观察者
        mContext.getContentResolver().notifyChange(uri,null);
        return uri;
    }

    //客户端执行delete时会跳到这里
    @Override
    public int delete(Uri uri,String selection, String[] selectionArgs) {
        Log.d(TAG,"delete");
        String table = getTableName(uri);
        if (table == null){
            throw new IllegalArgumentException("Unsupport URI:" + uri);
        }
        int count = mDb.delete(table,selection,selectionArgs);
        if (count > 0){
            getContext().getContentResolver().notifyChange(uri,null);
        }
        return count;
    }

    //客户端执行update时会跳到这里
    @Override
    public int update(Uri uri, ContentValues values,String selection,String[] selectionArgs) {
        Log.d(TAG,"update");
        String table = getTableName(uri);
        if (table == null){
            throw new IllegalArgumentException("Unsupport URI:" + uri);
        }
        int row = mDb.update(table,values,selection,selectionArgs);
        if (row > 0){
            getContext().getContentResolver().notifyChange(uri,null);
        }
        return row;
    }

    //执行SQL语句,添加数据
    private void initProviderData(){
        mDb = new DbOpenHelper(mContext).getWritableDatabase();//向DbOpenHelper类获取SQLiteDatabase!
        mDb.execSQL("delete from " + DbOpenHelper.BOOK_TABLE_NAME);//清空这张表
        mDb.execSQL("delete from " + DbOpenHelper.USER_TABLE_NAME);
        mDb.execSQL("insert into book values(3,'Android');");
        mDb.execSQL("insert into book values(4,'IOS');");
        mDb.execSQL("insert into book values(5,'Html5');");
        mDb.execSQL("insert into user(_id,name,sex) values(1,'jake',1);");
        mDb.execSQL("insert into user(_id,name,sex) values(2,'jasmine',0);");
    }

    //把客户端传来的Uri转为数据库中表的名称
    private String getTableName(Uri uri){
        String tableName = null;
        switch (sUriMatcher.match(uri)){//将Uri转换为对应的Uri_Code
            case BOOK_URI_CODE:
                tableName = DbOpenHelper.BOOK_TABLE_NAME;
                break;
            case USER_URI_CODE:
                tableName = DbOpenHelper.USER_TABLE_NAME;
                break;
            default:
                break;
        }
        return tableName;
    }
}

在AndroidManifest.xml文件要对ContentProvider进行设置:

<provider
	android:authorities="com.example.a20190130.BookProvider11"
	android:name=".BookProvider"
	android:permission="com.example.a20190130.PROVIDER"
	android:process=":provider"/>
  • android:authorities是ContentProvider的唯一标识;
  • android:permission指定了外界应用如果要访问ContentProvider,必须声明这个权限;
  • android:name与自己创建的ContentProvider对应;
  • android:process为ContentProvider开辟独立运行的进程;

第三步,在客户端访问ContentProvider:
Uri bookUri = Uri.parse("content://" + AUTHORITY + "/book")获取ContentProvider里的表,通过getContentResolver().insert()等对此表进行操作。
insert、query、delete、update等在ContentProvider中进行了重写。客户端对表的操作会对应到ContentProvider里重写的四大方法。

public class MainActivity extends AppCompatActivity {

    //ContentProvider的唯一标识符
    public static final String AUTHORITY = "com.example.a20190130.BookProvider11";
    private static final String TAG  = "aa20190131";
    Button button;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

//                //BookProvider中的query被调用了三次,这三次调用不在同一个线程中,它们运行在一个Binder线程中
//                Uri uri = Uri.parse("content://com.example.a20190130.BookProvider");
//                getContentResolver().query(uri,null,null,null,null);
//                getContentResolver().query(uri,null,null,null,null);
//                getContentResolver().query(uri,null,null,null,null);

                //要访问的是ContentProvider中的book表
                Uri bookUri = Uri.parse("content://" + AUTHORITY + "/book");
                ContentValues values = new ContentValues();
                values.put("_id",6);
                values.put("name","程序设计的艺术");
                getContentResolver().insert(bookUri,values);

                Cursor bookCursor = getContentResolver().query(bookUri,new String[]{"_id","name"},
                        null,null,null);
                while (bookCursor.moveToNext()){
                    Book book = new Book();
                    book.bookId = bookCursor.getInt(0);
                    book.bookName = bookCursor.getString(1);
                    Log.d(TAG, "query book: " + "bookId:" + book.bookId + " bookName:" + book.bookName);
                }
                bookCursor.close();

                Uri userUri = Uri.parse("content://" + AUTHORITY + "/user");
                Cursor userCursor = getContentResolver().query(userUri,new String[]{"_id","name","sex"},
                        null,null,null);
                while (userCursor.moveToNext()){
                    User user = new User();
                    user.userId = userCursor.getInt(0);
                    user.userName = userCursor.getString(1);
                    user.isMale = userCursor.getInt(2) == 1;
                    Log.d(TAG, "query user: " + "userId:" + user.userId + " userName:" + user.userName + " isMale:" + user.isMale);
                }
                userCursor.close();
            }
}

上一篇: Hive --自定义函数

下一篇: