Android 数据存储之 Content Providers

本文详细介绍了Android中ContentProvider的工作原理、添加及使用方法,强调了ContentProvider作为数据验证层的重要性和优势。通过ContentProvider,可以实现数据源与UI的抽象,确保无效数据无法直接进入数据库。文章还涵盖了ContentProvider的query、insert、update、delete等方法的调用过程,以及如何添加URI Matcher和数据验证。
摘要由CSDN通过智能技术生成

这里写图片描述

为什么要使用 Content Provider

在上篇文章中,我们看到 Activity 都是直接调用 PetDbHelper 来直接访问数据库的。所以只要我们知道插入的信息是正确的,这样的操作就没有问题。但不小心在 Activity 中插入了一个不良的数据(例如宠物的值为 -10kg),这种直接交互方法的缺陷就在于 它会将无效的数据直接插入到我们的数据库中,所以这里就有了 Content Provider-集中化数据的访问和编辑

在这个模式中,我们的 UI 代码会直接与 Content Provider 交互,而非直接与数据库交互。Content Provider 作为一个数据验证层(data validation),会在我们错误输入无效的数据时进行验证,如果数据存在错误,就会在这一步被捕捉到。它作为数据源和 UI 代码之间的附加层。它通常被称为抽象层(abstraction layer),因为 Content Provider 会抽象化数据存储的方式或隐藏数据存储的详情,所以 UI 代码在进行任何数据访问时,只需和 Content Provider 进行通信,Content Provider 会以 UI 看不到的方式对底层数据进行暗箱处理。因为 UI 不关心数据是存储在数据库中还是存储在单个文本文件中,所以如果在应用的更新版本中我们想将数据库换做不同的存储类型 UI 代码将保持不变,并继续与现有的 Content Provider 交互。

Content Provider 三大优势:

  • 作为数据源与 UI 代码之间的抽象层,可以帮助我们很好地进行数据验证;
  • 帮助我们与其它框架类完美协助;
  • 帮助我们轻松与其它应用分享数据

ContentProvider 工作原理

这里写图片描述

CatalogActivity 调用 CRUD (查询/插入/修改/删除)方法的任意一个,并传入一个 URI 指定其想与之交互的特定数据集,这个特定数据可以是数据库里某行中的特定名称,然后给定 URI 中的信息,ContentResolver 会将该消息发送到适当的 ContentProvider,而 ContentProvider 会和 PetDbHelper 进行交互,database 从而获取适当的数据并将它返回至调用者,返回的数据会回传至 ContentResolver,并最终返回至 CatalogActivity 以在 UI 中显示。

添加 ContentProvider 代码

在 data 包名下,创建 PetProvider 类继承自 ContentProvider,重写所有的方法。

public class PetProvider extends ContentProvider {
   

    /** Tag for the log messages */
    public static final String LOG_TAG = PetProvider.class.getSimpleName();

    /**
     * Initialize the provider and the database helper object.
     */
    @Override
    public boolean onCreate() {
        // TODO: Create and initialize a PetDbHelper object to gain access to the pets database.
        // Make sure the variable is a global variable, so it can be referenced from other
        // ContentProvider methods.
        return true;
    }

    /**
     * Perform the query for the given URI. Use the given projection, selection, selection arguments, and sort order.
     */
    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
                        String sortOrder) {
        return null;
    }

    /**
     * Insert new data into the provider with the given ContentValues.
     */
    @Override
    public Uri insert(Uri uri, ContentValues contentValues) {
        return null;
    }

    /**
     * Updates the data at the given selection and selection arguments, with the new ContentValues.
     */
    @Override
    public int update(Uri uri, ContentValues contentValues, String selection, String[] selectionArgs) {
        return 0;
    }

    /**
     * Delete the data at the given selection and selection arguments.
     */
    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        return 0;
    }

    /**
     * Returns the MIME type of data for the content URI.
     */
    @Override
    public String getType(Uri uri) {
        return null;
    }
}

在 AndroidManifest 文件中,添加代码 说明我们使用的是带这个 provider 标签的 ContentProvider。

<!--authorities:唯一指定设备上的 Content Provider,通常直接使用应用的包名即可-->
<!--exported:决定我们的 Content Provider 是否对其它应用可见-->
<provider
  android:name=".data.PetProvider"
  android:authorities="com.example.android.pets"
  android:exported="false" />

ContentProvider 方法调用

下面将介绍每种方法的调用。

query() 方法
这里写图片描述
CatalogActivity 使用 query() 方法调用 ContentResolver,为确定 ContentResolver 最终使用哪个 Provider, 我们在 query() 方法中传递了一个内容 URI。这里的 URI 帮助 指定数据库中我们感兴趣的资源。接下来 ContentResolver 从此 query() 方法中获得信息后,它会使用相同的 query() 方法调用合适的 Provider,这里我们知道了要调用的是 PetProvider。接下来为了获取数据,query() 方法会将传入的参数转换为 SQL 语句,然后用此对数据库执行操作。查询到信息后将返回一个 Cursor,它包含我们感兴趣的行,它会最终返回至最初调用此信息的 CatalogActivity。

insert() 方法
这里写图片描述
和 query() 方法比较相似,但是它有一个附加参数 ContentValues,此参数包含我们实际想插入数据库中的信息,而 Uri 告诉我们插入的位置。同样 CatalogActivity 使用此 insert() 方法调用 ContentResolver,然后 ContentResolver 使用其自己的名称相同的 insert() 方法来调用合适的 provider,这里仍然是 PetProvider,以将我们的特定值插入数据库中。insert() 方法传入的信息会被转换为 SQL 用来决定将什么值插入到数据库中的什么位置,但对于 insert() 方法返回的将不是 Cursor,而是一个 Uri 告诉我们指定宠物在数据库中插入的位置。

update() 方法
这里写图片描述

分析过程同上,update() 方法返回的将是数据库中更新的行的编号。
delete() 方法
这里写图片描述
分析过程同上,delete() 方法返回的将是数据库中被删除行的编号。

什么是 Url

在使用 Provider 时,我们基本上需要告诉它两件事:

  1. 我们想要执行什么操作(查询/插入/修改/删除)?
  2. 我们想在这个操作中使用什么数据&#
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值