【问题标题】:Does Android OS has one `ContentResolver` object that is shared by all the apps or does each app has their own instance of `ContentResolver`?Android 操作系统是否有一个由所有应用程序共享的“ContentResolver”对象,或者每个应用程序都有自己的“ContentResolver”实例?
【发布时间】:2018-09-07 22:17:12
【问题描述】:

我正在学习关于 Udacity 的 Android 课程,并在标题中遇到了一位同学提出的问题。

Youtube link to lesson

引用视频:

ContentResolver resolver = getContentResolver();
Cursor cursor = resolver.query(DroidTermsExampleContract.CONTENT_URI, null, null, null, null);

此代码访问正确的内容提供程序并获取一些数据 从中。我们这里有一些新的词汇概念,所以我要走了 把它分解。第一个新概念是 ContentResolver。所以我们的 原图相当简单。让我们看看这张图 我们以前见过。

这张图更准确的版本是这样的。

并且 此绘图涉及内容解析器。那么这样做的目的是什么 让这个类位于您的应用程序和直接访问 内容提供者?

如果你仔细想想,有多个内容 您的手机上的提供商,并且您在添加更多内容提供商时 下载存储本地数据的应用程序,这些应用程序使用内容提供程序。 除了 DroidTermsExample 内容提供者之外,您还有一个内容 联系人提供程序,您的设备有一个用于 设备,一种跟踪用户警报的设备,日历提供程序, 和其他一些人。

此外,您的应用并不是唯一在 设备。还有其他应用程序可能也在使用内容 供应商并行。管理内容提供​​商正在与之交谈的内容 哪些应用程序,并保持所有数据同步,可能会变成一个巨大的 交通阻塞。这就是内容解析器的用武之地。

内容解析器充当每个应用程序和 内容提供者,或它想要访问的提供者。它处理 进程间通信并使一切保持同步和运行 顺利。 即使您有五个进程访问两个内容 供应商。

因此,无论您想在何处使用内容提供程序,您都需要 通过 ContentResolver 来完成。好的,现在你知道这是什么了 第一行正在做,

ContentResolver resolver = getContentResolver();

让我们参考系统的内容 解析器。这是访问内容提供者的下一步。

视频中的解释(尤其是上面的粗体标记线)清楚地让我认为Android OS 有一个ContentResolver

它的工作是让所有想要与一个或多个应用程序的内容提供者对话的应用程序的生活更轻松。


然而,同学们似乎有相反的理解。给出的一些论点是:

来自androiddesignpatterns

内容解析器是您的单个全局实例 提供对您(和其他应用程序)的访问权限的应用程序 内容提供者。

来自Android docs

当您想要访问内容提供程序中的数据时,您可以使用 ContentResolver 对象在你的应用程序的 Context 中进行通信 以提供者为客户。

声明:

既然在你的应用程序中提到了 ContentResolver 对象 上下文,因此每个应用程序都有自己的内容解析器

我仍然有一个简单的公平理解,即操作系统提供了一个 ContentResolver,然后将此解析器带到给定应用程序的上下文中以使用它。不可以吗?

这是我的第一门 Android 课程,我绝对是初学者。如果我对这个概念有错误的理解,有人可以澄清一下吗?

【问题讨论】:

  • 是的,你是对的!!

标签: java android android-contentprovider android-contentresolver


【解决方案1】:

在任何给定的应用程序中,ContentResolver 类只有 一个 单个实例。

查看Android源代码中实际ContextImpl类(实际实现Context接口的类)的源代码,您会发现抽象ContentResolver类的内部静态ApplicationContentResolver子类管理所有应用程序和系统服务器之间的通信。 ApplicationContentResolver 的实例在 ContextImpl 的构造函数中创建,并且对于该上下文(或应用程序)是唯一的。

ApplicationContentResolver 将它的调用委托给ActivityThread 类,该类负责管理应用程序的主线程 并向系统服务器提供 IPC 通信(通过活页夹)。在ActivityThread 类中,您会发现像ActivityThread#acquireProvider() 这样的调用,它们要么重用现有的提供者(并增加它的引用计数),要么要求 ActivityManagerNative 获取提供者的新实例通过系统服务器。这是一个重要的步骤,因为此时系统服务器将检查调用应用程序是否具有所需的权限。

一旦系统服务器决定调用应用程序有足够的权限来使用ContentProvider,它就会创建 ContentProvider重新使用 on if它存在并将对它的引用返回给调用应用程序。

来自ContentProvider 上的文档,

数据访问方法可以同时从多个线程调用,并且必须是线程安全的。其他方法(如 onCreate())仅从应用程序主线程调用,必须避免执行冗长的操作。

这意味着单个 ContentProvider 实例在多个应用程序之间共享,并且它的生命周期由系统管理(就像其他组件一样)。

因此总结一下,每个应用程序有 一个 单个 ContentResolver 实例,并且整个应用程序也有 一个 单个 ContentProvider 实例(对于给定权限)系统。

【讨论】:

  • 总结一下,每个应用程序只有一个 ContentResolver 实例... 所以你的意思是说在我假设的有 5 个应用程序 上面(假设都需要 ContentResolver),我的设备上有 5 个ContentResolver 实例?
  • 确实如此!由于每个应用程序都有自己的Context,并且每个上下文都有自己的解析器(请参阅this),这意味着每个应用程序都有一个与之关联的内容解析器
  • P.S.我也在上同样的课程:)你也可以在这里分享帖子的链接吗?还有你的把手?
  • @VikasPrasad 如果它解决了你的问题,你应该接受这个答案。
  • @riyaz-ali 我的句柄是 [at]Vikas Prasad
猜你喜欢
  • 1970-01-01
  • 2021-03-31
  • 1970-01-01
  • 2015-06-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多