使用ContentProviderClient和ContentResolver访问内容提供程序

时间:2011-02-22 22:39:58

标签: android android-contentprovider android-contentresolver

documentation on Android content providers描述了使用从ContentResolver获取的getContentResolver()来访问内容。

但也有ContentProviderClient,可以从getContentResolver().acquireContentProviderClient(authority)获取。它似乎提供了ContentResolver中可用的相同方法来访问提供者的内容。

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

5 个答案:

答案 0 :(得分:90)

您的Android设备有许多数据库,每个数据库都由唯一的内容管理机构标识。这是内容中的“域名”等效部分:// uri - 第一个斜杠之前的所有内容。

ContentResolver存储提供从String contentAuthorityContentProvider的映射的数据。当您调用ContentResolver.query()update()或您拥有的内容时,URI将被分解为其组件,标识contentAuthority字符串,并且contentResolver必须在该映射中搜索匹配的字符串,并指示查询到合适的提供者。这种昂贵的搜索发生在每次调用期间,因为URI可能与呼叫不同,具有不同的contentAuthority。此外,设置和拆除与特定提供商的连接可能会涉及一些成本 - 它不能在呼叫之间重复使用。我不确定那里涉及的开销,这是一些非常深的操作系统级代码。

相比之下,当你致电acquireContentProviderClient(authority)时,“我需要什么提供者?”查询已完成一次,您将获得一个ContentProviderClient,它实际上是ContentProvider的直接链接。 (您和提供程序之间存在一些涉及跨线程通信和并发锁定的粘合剂)。但是,当您使用ContentProviderClient时,您将直接与提供商讨论您请求的权限。这消除了不断重新计算“我想要哪个提供商?”的浪费。

注意:acquireContentProviderClient() documentation:如果您获得ContentProviderClient,“来电者必须通过调用ContentProviderClient.release()来表明他们已完成提供商的操作,这将允许系统发布提供程序它确定没有其他原因使其保持活动状态。“因此,实际上,让陈旧的客户端打开将迫使提供程序在后台继续作为服务运行。所以,记得要清理!

摘要:

许多调用不同内容的权限:使用ContentResolver

重复拨打同一个管理局:获取并使用ContentProviderClient。记得在完成后释放()它。

答案 1 :(得分:7)

好的,但请注意,仅当 ContentProvider 在与活动相同的过程中运行时,它才有效。

请注意方法getLocalContentProvider()的文档:

  

如果ContentProvider在不同的进程中运行,则为null   将被退回。如果您知道自己正在运行,则可以使用此选项   与提供者相同的进程,并希望直接访问它   实施细节。

答案 2 :(得分:4)

我认为另一个导入区别是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

答案 3 :(得分:2)

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

答案 4 :(得分:0)

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

像这样实施ContentProvider#shutdown()

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

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

getContext()
       .getContentResolver()
       .acquireContentProviderClient(URI)
       .getLocalContentProvider()
       .shutdown();