为什么 Android 服务在测试时不是单例的?

发布于 2025-01-03 14:51:49 字数 272 浏览 3 评论 0原文

当运行大量测试套件时,我注意到我的一个 Android 服务不再是单例的。 Android 服务应该是单例的,但是当使用 ServiceTestCase 时,我的引用计数超过 1。(在 onCreate 中递增,在 onDestroy 中递减)。 从测试用例调用startService或bindService应该会导致第二个onBind或onStartCommand,但绝不会在第一个onDestroy之前导致第二个onCreate。

这是因为单元测试绕过了 Zygote 吗?如果是这样,我该如何解决这个问题?

When running a large set of testsuites, I noticed that one of my Android Services isn't singleton anymore. An Android Service is supposed to be singleton but when using a ServiceTestCase my reference count went above 1. (incremented in onCreate, decremented in onDestroy).
Calling startService or bindService from a testcase should result in a second onBind or onStartCommand but should never result in a second onCreate before the first onDestroy.

Is this because the unit test is bypassing Zygote? And if so, how can I fix this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

心奴独伤 2025-01-10 14:51:49

我注意到我的 Android 服务之一不再是单例

无论您是在真实运行环境下还是在仪器测试下启动/绑定它,Android 服务都是单例的。通过单例,我的意思是堆中存在一个唯一的对象,可以有多个引用指向它。

从测试用例调用startService或bindService应该会导致第二个onBind或onStartCommand

这不是真的,如官方开发指南中所述:“多个客户端可以同时连接到服务。但是,系统会调用服务的 onBind () 方法仅在第一个客户端绑定时检索 IBinder,然后系统将相同的 IBinder 传递给任何其他绑定的客户端,而无需再次调用 onBind()。”

但决不应该在第一个 onDestroy 之前导致第二个 onCreate

根据官方开发指南:“如果您允许启动并绑定服务,那么当服务启动后,系统不会销毁该服务当所有客户端解除绑定时,您必须通过调用 stopSelf() 或 stopService() 显式停止服务。”

因此,幕后的场景是,第一次调用启动或绑定服务时,Service.onCreate () 方法被调用((在调用 onStartCommand() 或 onBind() 之前)在堆上创建一个唯一的对象并返回对其的引用(引用计数 = 1),此后,每次调用 start 或 bind service 时,Service.onStartCommand () 执行时不会在堆上创建新对象(通过调用 Service.onCreate()),而是返回同一对象的第二个引用点(现在引用计数 = 2),每次调用 unbind 时,引用计数都会减少一,直到参考count 达到 0 时,调用 Service.onDestroy() 方法,最终清理堆上的对象。

您可以在此处找到我在官方开发指南中以斜体字引用的所有详细信息

I noticed that one of my Android Services isn't singleton anymore

Android Services is singleton regardless whether your start/bind it under real running environment or under instrumentation test. By singleton, I mean a unique object live in the heap which can have multiple references point to it.

Calling startService or bindService from a testcase should result in a second onBind or onStartCommand

this is not true, as stated in the official dev guide: "Multiple clients can connect to the service at once. However, the system calls your service's onBind() method to retrieve the IBinder only when the first client binds. The system then delivers the same IBinder to any additional clients that bind, without calling onBind() again."

but should never result in a second onCreate before the first onDestroy

According to the official dev guide: "If you do allow your service to be started and bound, then when the service has been started, the system does not destroy the service when all clients unbind. Instead, you must explicitly stop the service, by calling stopSelf() or stopService()."

So the scenario behind the scenes is, by first time you call start or bind service, Service.onCreate() method is called ((before calling either onStartCommand() or onBind()) to create a unique object on the heap and a reference to it is returned (reference count = 1), after that, each time you call start or bind service, Service.onStartCommand() is perform without creating new object (by calling Service.onCreate()) on the heap, instead, return a second reference point to the same object (now reference count = 2), each time you call unbind, reference count decrease by one, until reference count reach to 0, Service.onDestroy() method is called and finally clean up the object on the heap.

You can find all details I referenced in italic from the official dev guide here.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文