65

有关 Android 内容提供程序的文档描述了使用ContentResolvergetContentResolver()获取的 来访问内容。

但是也有一个ContentProviderClient,可以从 获得getContentResolver().acquireContentProviderClient(authority)。它似乎提供了或多或少相同的方法ContentResolver来访问来自提供者的内容。

我什么时候应该使用 aContentProviderClient而不是ContentResolver直接使用?有什么好处?

4

5 回答 5

96

您的 android 设备有许多数据库,每个数据库都由唯一的 Content Authority 标识。这是 content:// uri 中的“域名”等效部分——第一个斜杠之前的所有内容。

ContentResolver存储提供从String contentAuthority到的映射的数据ContentProvider。当您调用ContentResolver.query()orupdate()或您拥有什么时,URI 将被解析为其组件,识别 contentAuthority 字符串,并且 contentResolver 必须在该映射中搜索匹配的字符串,并将查询定向到正确的提供程序。这种昂贵的搜索发生在每次调用期间,因为每次调用的 URI 可能不同,并且 contentAuthority 也不同。此外,建立和断开与特定提供商的连接可能会产生一些成本——它不能在调用之间重复使用。我不确定那里涉及的开销,那是一些非常深的操作系统级代码。

相比之下,当您致电acquireContentProviderClient(authority)时,“我需要什么提供者?” 查找只进行一次,您将获得一个ContentProviderClient本质上是指向ContentProvider. (您和提供者之间存在一些涉及跨线程通信和并发锁定的粘合剂)。但是,当您使用 时ContentProviderClient,您将直接与提供者对话以获得您请求的权限。这消除了不断重新计算“我想要哪个提供商?”的浪费。

注意:根据acquireContentProviderClient() 文档:如果您获得 ContentProviderClient, “调用者必须通过调用ContentProviderClient.release()表明他们已与提供者一起完成,这将允许系统释放提供者它确定没有其他保持它活跃的原因。” 所以本质上,让陈旧的客户端保持打开状态将迫使提供者继续在后台作为服务运行。所以,记得清理!

概括:

多次调用不同的 contentAuthorities: 使用ContentResolver.

重复调用相同的权限: 获取和使用ContentProviderClient. 完成后记得释放()它。

于 2011-03-08T14:14:07.810 回答
8

好的,但请注意,它仅在ContentProvider与 Activity 在同一进程中运行时才有效。

方法文档中的注释getLocalContentProvider()

如果 ContentProvider 在不同的进程中运行,则将返回 null。如果您知道自己与提供者在同一进程中运行,并且希望直接访问其实现细节,则可以使用此选项。

于 2012-10-29T07:54:24.210 回答
5

我认为另一个重要的区别是 ContentProviderClient 可以转换为您的自定义提供程序对象并访问除 CRUD 之外的其他方法。

ContentProvider cp = getContentResolver().acquireContentProviderClient(mCurUri).getLocalContentProvider();
yourProvider fld = (yourProvider)cp;
fld.query(...);           // you can query as ContentResolver
fld.addFolder(newFolder); // also can invoke the extend method of your custom ContentProvider
于 2012-07-23T12:11:33.760 回答
2

我发现了以下区别:我在应用程序 A 中编写了自己的自定义内容提供程序。我在应用程序 B 中编写了一个主屏幕小部件。当我尝试通过我的小部件中的 ContentResolver 访问应用程序 A 的 ContentProvider 时,我得到一个“找不到提供程序”信息”错误。当我改为通过 ContentResolver 获取 ContentProviderClient 并通过 ContentProviderClient 查询时,它会起作用。我无需更改任何其他内容,只需使用 ContentProviderClient 而不是 ContentResolver。我对这种行为没有真正的解释,也没有在互联网上找到关于为什么会这样的信息。我不知道,这是否是小部件的一个特殊怪癖,因为我没有从应用 B 中的活动尝试它(应用 B 只是一个小部件,没有活动)。

于 2012-03-09T21:17:29.633 回答
0

ContentProviderClient 的其中一种用法有助于在测试中访问 ContentProvider 的一些方法。例如,我在单元测试中使用shutdown()方法来避免多个测试实例化多个内容提供者。

像这样实现ContentProvider#shutdown()

@Override
public void shutdown() {
    openHelper.close();
    super.shutdown();
}

并在测试方法结束时,调用shutdown()使用ContentProviderClient清理测试,以便其他测试可以使用内容提供程序:

getContext()
       .getContentResolver()
       .acquireContentProviderClient(URI)
       .getLocalContentProvider()
       .shutdown();
于 2016-04-08T13:32:03.537 回答