IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> Android - 跨应用访问数据实战之 ContentProvider -> 正文阅读

[大数据]Android - 跨应用访问数据实战之 ContentProvider

????????四大组件之一,但我却没有一次尝试过,只是曾经在文档中看到过这么个东西,为了弥补自己的遗憾,特此记录下本次尝试。 虽然只有查看和添加,但删除和更新的方法也都实现了,并且内容全部写死了,可以通过 Button 的点击事件来查看。CP-demo 可实现增删改查,cp-2只写了查看。demo 地址写在最后。

内容提供程序以一个或多个表的形式将数据呈现给外部应用,这些表与关系型数据库中的表类似。行表示提供程序收集的某种类型数据的实例,行中的每一列表示为一个实例所收集的单个数据。

? ? ? ? 因此,看过了介绍之后感觉这就是共享数据库(不知道我理解的对不对)。而大部分我们需要的都是读取其他应用,如通讯录等。本文自定义的 MyProvider 也就是实现对数据库的增删改查。

public class MyProvider extends ContentProvider {

    private static final String TAG = "MyProvider";
    private static final int TITTLE = 1;
    private static final int TITTLE_ID = 2;
    private static final UriMatcher uriMatcher = getUriMatcher();
    private static final String DATABASE_TABLE = "test";

    private static UriMatcher getUriMatcher() {
        UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
        uriMatcher.addURI(Constants.PROVIDER_NAME, "test", TITTLE);
        uriMatcher.addURI(Constants.PROVIDER_NAME, "test/#", TITTLE_ID);
        return uriMatcher;
    }

    private DBHelper dbHelper = null;
    private SQLiteDatabase database = null;

    @Override
    public boolean onCreate() {
        Context context = getContext();
        dbHelper = new DBHelper(context);
        database = dbHelper.getWritableDatabase();
        return true;
    }

    @Nullable
    @Override
    public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection,
                        @Nullable String[] selectionArgs, @Nullable String sortOrder) {
        Cursor cursor = null;
        switch (uriMatcher.match(uri)) {
            case TITTLE_ID:
                cursor = database.query(DATABASE_TABLE, projection, "_id = ",
                        new String[]{uri.getPathSegments().get(1)}, null,
                        null, sortOrder);
                break;
            case TITTLE:
                cursor = database.query(DATABASE_TABLE, projection, selection, selectionArgs, null,
                        null, sortOrder);
                break;
            default:
                throw new IllegalArgumentException("Unknown URI " + uri);
        }
        return cursor;
    }


    /**
     * 关于MIME类型,android 是这么规定的。
     * 1.必须以vnd开头
     * 2.如果是多条记录,后面接android.cursor.dir/,如果是单条记录,后面接android.cursor.item/
     * 3.最后 加上"vnd.<authority>.<path>"
     *
     * @param uri
     * @return
     */
    @Nullable
    @Override
    public String getType(@NonNull Uri uri) {
        switch (uriMatcher.match(uri)) {
            case TITTLE:
                return "vnd.android.cursor.dir/vnd.com.flyscale.cp.data";
            case TITTLE_ID:
                return "vnd.android.cursor.item/vnd.com.flyscale.cp.data";
            default:
                throw new IllegalArgumentException("Unsupported URI: " + uri);
        }
    }

    @Nullable
    @Override
    public Uri insert(@NonNull Uri uri, @Nullable ContentValues contentValues) {
        long rowId = database.insert(DATABASE_TABLE, null, contentValues);
        if (rowId > 0) {
            Uri mUri = ContentUris.withAppendedId(uri, rowId);
            return mUri;
        }
        throw new SQLException("Failed to insert row into " + uri);
    }

    @Override
    public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
        int rowIDs;
        switch (uriMatcher.match(uri)) {
            case TITTLE_ID:
                String tittleID = uri.getPathSegments().get(1);
                rowIDs = database.delete(DATABASE_TABLE, "_id = ", new String[]{tittleID});
                break;
            case TITTLE:
                rowIDs = database.delete(DATABASE_TABLE, selection, selectionArgs);
                break;
            default:
                throw new IllegalArgumentException("Unknown URI " + uri);
        }
        return rowIDs;
    }

    @Override
    public int update(@NonNull Uri uri, @Nullable ContentValues contentValues, @Nullable String selection, @Nullable String[] selectionArgs) {
        int rowIDs;
        Log.e(TAG, "query: " + uriMatcher.match(uri));
        switch (uriMatcher.match(uri)) {
            case TITTLE_ID:
                String tittleID = uri.getPathSegments().get(1);
                rowIDs = database.update(DATABASE_TABLE, contentValues, "_id = ", new String[]{tittleID});
                break;
            case TITTLE:
                rowIDs = database.update(DATABASE_TABLE, contentValues, selection, selectionArgs);
                break;
            default:
                throw new IllegalArgumentException("Unknown URI " + uri);
        }
        return rowIDs;
    }
}

? ? ? ? 调用方法的过程涉及到两个类。

ContentValues类和Bundle类很类似,都是使用HashMap的泛型形式来存储的,只能存储基本类型的数据。
ContentResolver,具体的实现过程通过该类。

????????

contentValues.put("tittle", "Hello world");
Uri uri = contentResolver.insert(Constants.CONTENT_URI, contentValues);

int cursor = contentResolver.delete(Constants.CONTENT_URI,null, null);

contentValues.clear();
contentValues.put("tittle", "Hello world - 改");
int cursor2 = contentResolver.update(Constants.CONTENT_URI, contentValues, null, null);

Cursor cursor3 = contentResolver.query(Constants.CONTENT_URI,
        null, null, null, null);
while(cursor3.moveToNext()) {
    Log.d(TAG, "initView: " + cursor3.getString(cursor3.getColumnIndex("tittle")));
}
cursor3.close();

在官网看到的ContentResolver.query() 方法:

// Queries the user dictionary and returns results
cursor = getContentResolver().query(
? ? UserDictionary.Words.CONTENT_URI, ? // The content URI of the words table
? ? projection, ? ? ? ? ? ? ? ? ? ? ? ?// The columns to return for each row
? ? selectionClause, ? ? ? ? ? ? ? ? ? // Selection criteria
? ? selectionArgs, ? ? ? ? ? ? ? ? ? ? // Selection criteria
? ? sortOrder); ? ? ? ? ? ? ? ? ? ? ? ?// The sort order for the returned rows

Query() 与 SQL 查询的比较。

query() 参数SELECT 关键字/参数备注
UriFROM?table_nameUri?映射至提供程序中名为 table_name 的表。
projectioncol,col,col,...projection?是检索到的每个行所应包含的列的数组。
selectionWHERE?col?=?valueselection?指定选择行的条件。
selectionArgs(没有完全等效项,选择参数会替换选择子句中的???占位符。)
sortOrderORDER BY?col,col,...sortOrder?指定在返回的?Cursor?中各行的显示顺序。

????????上述的方法通过 contentResolver 调用内容提供器的功能,实质上则是通过 Content Provide 来实现的。在 MyProvider 已实现具体功能。为了方便,表名为 test , 只有一个 tittle。下面的是导出来的 db 文件。

public class DBHelper extends SQLiteOpenHelper {

    private static final String DATABASE_NAME = "data.db";
    private static final String TABLE_NAME = "test";
    private static final String SQL_CREATE = "CREATE TABLE " + TABLE_NAME +
            " (_id INTEGER PRIMARY KEY, tittle TEXT )";
    private static final String SQL_DROP = "DROP TABLE IS EXISTS " + TABLE_NAME ;

    public DBHelper(Context context) {
        super(context, DATABASE_NAME, null, 1);
    }

    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {
        sqLiteDatabase.execSQL(SQL_CREATE);
    }

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) {
        sqLiteDatabase.execSQL(SQL_DROP);
        onCreate(sqLiteDatabase);
    }

    public Cursor getData(String id, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
        SQLiteQueryBuilder sqliteQueryBuilder = new SQLiteQueryBuilder();
        sqliteQueryBuilder.setTables(TABLE_NAME);

        if(id != null) {
            sqliteQueryBuilder.appendWhere("_id" + " = " + id);
        }

        if(TextUtils.isEmpty(sortOrder)) {
            sortOrder = "tittle";
        }
        Cursor cursor = sqliteQueryBuilder.query(getReadableDatabase(),
                projection,
                selection,
                selectionArgs,
                null,
                null,
                sortOrder);
        return cursor;
    }
}

?最后需要在清单文件中注册,authorities 是 provider所在的包的名字 + provider 本身定义的名称。

<provider
    android:authorities="com.flyscale.cp.data"
    android:name=".MyProvider"
    android:exported="true" />

对了不要忘记权限声明

<uses-permission android:name="android.permission.READ_USER_DICTIONARY"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

传送门:ContentProvider demo

  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2022-03-24 00:37:48  更:2022-03-24 00:40:47 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 7:41:40-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码