为什么在测试时Android Service不是单例?

4
当运行一组大型测试套件时,我注意到我的一个Android服务不再是单例。Android服务应该是单例的,但当使用ServiceTestCase时,我的引用计数超过了1(在onCreate中递增,在onDestroy中递减)。 从测试用例中调用startService或bindService应该导致第二个onBind或onStartCommand,但绝不能在第一个onDestroy之前导致第二个onCreate。
这是因为单元测试绕过了Zygote吗?如果是这样,我该如何解决?
1个回答

5
我注意到我的一个Android服务不再是单例了。
无论在实际运行环境下还是在测试环境下启动/绑定它,Android服务都是单例的。所谓单例指的是存储在堆中的唯一对象,可以有多个引用指向它。
从测试用例中调用startService或bindService应该会导致第二次onBind或onStartCommand调用。
这是不正确的,正如官方开发指南所述:“多个客户端可以同时连接到服务。但是,当第一个客户端绑定时,系统会调用您的服务的onBind()方法来检索IBinder。然后,系统将相同的IBinder传递给任何额外的绑定客户端,而无需再次调用onBind()。”
但是,在第一个onDestroy之前不应该再出现第二个onCreate。
根据官方开发指南:“如果允许服务启动并绑定,则当服务已启动时,当所有客户端取消绑定时,系统不会销毁服务。相反,您必须显式停止服务,通过调用stopSelf()或stopService()。”
当您第一次调用start或bind服务时,幕后情景是,将调用Service.onCreate()方法(在调用onStartCommand()或onBind()之前),以在堆上创建一个唯一对象,并返回对其的引用(引用计数= 1)。之后,每次调用start或bind服务时,Service.onStartCommand()都会执行,而不会在堆上创建新对象(通过调用Service.onCreate()),而是返回指向同一对象的第二个引用点(现在引用计数= 2)。每次调用unbind时,引用计数减少一个,直到引用计数达到0,调用Service.onDestroy()方法,最终清除堆上的对象。
您可以从官方开发人员指南here中找到我参考的所有详细信息。

onDestroy只有在调用stopSelf和最后一个unbind时才会被调用,但我不调用stopself,因为这个服务需要一直保持运行状态。所以你的意思是我必须在onCreate()中自己实现singleton,因为它可能会被调用多次? - Huupke
Singleton是由框架处理的。根据开发指南:_系统会在服务首次创建时调用Service.onCreate()方法,如果服务已经运行,则不会调用此方法。_每次调用startService()方法时都会调用Service.onStartCommand()方法。我已更新我的答案。 - yorkw
1
所以我的问题还是一样的,因为我仍然看到onCreate被调用了两次! - Huupke
2
据我所知,onCreate() 可能会在配置更改时被多次调用。但不用担心 - Service 作为单例正在工作 :) - alex
Service.onCreate() 方法被调用(在调用 onStartCommand() 或 onBind() 之前)以在堆上创建一个唯一的对象。onCreate 不是构造函数 - 实际上服务是在哪里实例化的(构造函数在哪里调用)?你知道吗? - Mr_and_Mrs_D

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接