documentation on Android content providers描述了使用从ContentResolver
获取的getContentResolver()
来访问内容。
但也有ContentProviderClient
,可以从getContentResolver().acquireContentProviderClient(authority)
获取。它似乎提供了ContentResolver
中可用的相同方法来访问提供者的内容。
我应该何时使用ContentProviderClient
而不是直接使用ContentResolver
?有什么好处?
答案 0 :(得分:90)
您的Android设备有许多数据库,每个数据库都由唯一的内容管理机构标识。这是内容中的“域名”等效部分:// uri - 第一个斜杠之前的所有内容。
ContentResolver
存储提供从String contentAuthority
到ContentProvider
的映射的数据。当您调用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();