[英]Why is AIDL/Messenger bound to a Service?
Scenario: I have a Controller
(normal Java class) that must be able to pilot several Slave
s. 场景:我有一个
Controller
(普通的Java类),它必须能够导航几个Slave
。
A Slave
's nature can differ, so that it can either be: Slave
的本性可以有所不同,因此它可以是:
Service
, let's call it a ServiceSlave
: the lifecycle of this object usually differs from the application's components (say, it does not depend on the current activity) Service
,我们称之为ServiceSlave
:该对象的生命周期通常不同于应用程序的组件(例如,它不依赖于当前活动) ObjectSlave
: the lifecycle of this object is somewhat bound to the scope in which it is created (say, the current activity) ObjectSlave
:这个对象的生命周期在某种程度上与创建它的范围有关(比如当前的活动) What these two types of Slave
s have in common, is that they can reside in different processes . 这两种类型的
Slave
的共同之处在于它们可以存在于不同的进程中 。
Because of this last "requirement", I immediately turned my attention to AIDL
/ Messenger
as the form of communication between a Controller
and a Slave
, since it provides IPC. 由于这最后的“要求”,我立即将注意力转移到
AIDL
/ Messenger
作为Controller
和Slave
之间的通信形式,因为它提供了IPC。
However, it seems that AIDL
(and in turn Messenger
, since it should be based on AIDL as well) has only been defined if you are to work with a Service
. 但是, 如果您要使用
Service
似乎只定义了AIDL
(以及Messenger
,因为它应该也基于AIDL)。 That is, there is no way for me to implement an AIDL
-based interface without an IBinder
object, which usually is provided in the onServiceConnected
method. 也就是说,我没有办法在没有
IBinder
对象的情况下实现基于AIDL
的接口, IBinder
对象通常在onServiceConnected
方法中提供。
FIRST QUESTION : can AIDL
really be used only when dealing with a Service
? 第一个问题 :
AIDL
真的只能在处理Service
时使用吗? If it is, why so? 如果是,为什么呢?
Now, consider my scenario. 现在,考虑一下我的情景。 I would like, as any other good developer would, to write a single, elegant interface that allows the
Controller
to pilot every Slave
, regardless of their nature. 正如任何其他优秀的开发人员所希望的那样,我希望编写一个优雅的界面,允许
Controller
每个Slave
,无论其性质如何。 The only solution that came to my mind so far involves using Intent
s and BroadcastReceiver
s, all conveniently wrapped in dedicated Java classes. 到目前为止,我想到的唯一解决方案是使用
Intent
和BroadcastReceiver
,它们都可以方便地包含在专用的Java类中。
SECOND QUESTION : is this the only viable way? 第二个问题 :这是唯一可行的方法吗? Am I overseeing something?
我在监督什么吗?
EDIT 编辑
I guess I should've given more details on what the Controller
element actually does. 我想我应该提供有关
Controller
元素实际功能的更多细节。 It is a component that is loosely coupled with several UI widgets, who subscribe to it. 它是一个与几个UI小部件松散耦合的组件,他们订阅了它。 It has been designed (willingly) so that it doesn't need a reference to a
Context
. 它已被设计(自愿),因此它不需要对
Context
的引用。 So it doesn't need or use UI widgets directly, but in turn those widgets depend on the Controller
. 因此它不需要或直接使用 UI小部件,但反过来这些小部件依赖于
Controller
。
This is a good, but not a simple question to answer. 这是一个很好但不是一个简单的问题。 Like most things, there are multiple approaches to take to solve this type of problem.
像大多数事情一样,有多种方法可以解决这类问题。 The first thing to examine is whether or not your
Controller
needs or uses a UI component. 首先要检查的是
Controller
是否需要或使用UI组件。 If not, then you'll need to encapsulate it in a Service
. 如果没有,那么您需要将其封装在
Service
。 Activity
lifecycle is such that it will only be running when it is the current thing on screen. Activity
生命周期是这样的,只有当它是屏幕上的当前事物时它才会运行。 As soon as the user presses HOME or BACK it is either stopped or destroyed, respectively. 一旦用户按下HOME或BACK,它就会分别停止或销毁。 Starting another app via notification or from within your app will have an effect similar to pressing HOME: your
Activity
will be paused. 通过通知或在您的应用程序中启动另一个应用程序将产生类似于按HOME的效果:您的
Activity
将暂停。
So, assuming you don't need/want UI for your Controller
, you have numerous things at your disposal: 因此,假设您不需要/想要
Controller
UI,您可以使用大量的东西:
Intent
s to take some action. Intent
以采取一些措施。 The Service
could then fire back broadcasts or start a specific "slave" Activity
. Service
可以重新开始广播或启动特定的“奴隶” Activity
。 If interested in this, explore the use of the IntentService
to better manage the threading and prevent ANR of your app. IntentService
来更好地管理线程并防止应用程序出现ANR。 Intent
and have your slave send a Messenger
object it has created as an extra within the Intent
. Intent
并让您的slave发送一个它在Intent
作为额外创建的Messenger
对象。 At that point the Service
can send messages to the Messenger
, which is owned by the slave Activity
and will be delivered to a specific Handler
. Service
可以向Messenger
发送消息,该Messenger
由从属Activity
拥有,并将传递给特定的Handler
。 You do not need a custom AIDL exposed interface for options 2 and 3. You are correct in that you must define an AIDL interface if you are going to use a bound service and your Service.onBind()
method must return an instance of your binder interface stub implementation. 您不需要为选项2和3提供自定义AIDL公开接口。如果要使用绑定服务并且
Service.onBind()
方法必须返回绑定器的实例,则必须定义AIDL接口Service.onBind()
接口存根实现。
All of that being said, you could use any of the 3 approaches to meet your goal of working with slave classes which reside in either Activity
or Service
instances. 所有这些,您可以使用这3种方法中的任何一种来实现使用驻留在
Activity
或Service
实例中的slave类的目标。 The advantage of using the AIDL or Messenger
approaches is a reduction in context switching (more efficient) since you're not sending Intent
objects. 使用AIDL或
Messenger
方法的优点是减少了上下文切换(更高效),因为您没有发送Intent
对象。 Each time you send an Intent
, the sender contacts the ActivityManagerService
running in a system process to resolve where the Intent
is to be delivered. 每次发送
Intent
,发件人都会联系在系统进程中运行的ActivityManagerService
,以解析Intent
传递位置。 With AIDL and Messenger
, only the initial bindService()
or startService()
calls reach out to the ActivityManagerService
. 使用AIDL和
Messenger
,只有初始bindService()
或startService()
调用才能访问ActivityManagerService
。 After that point the communication is performed using direct binders between the two processes. 在此之后,使用两个进程之间的直接绑定器执行通信。
Turns out AIDL
and Binder
are not tied to Service
s. 事实证明
AIDL
和Binder
与Service
无关。
While it is true that a IBinder
reference is provided only when binding to a Service
, the framework offers the Binder
class, which already implements the IBinder
interface. 虽然只有在绑定到
Service
时才提供IBinder
引用,但框架提供了Binder
类,它已经实现了IBinder
接口。
Moreover, a Binder
instance works transparently across processes and it is not required to live in a Service
context. 此外,
Binder
实例跨进程透明地工作,并且不需要存在于Service
上下文中。
[still elaborating, will provide a scheme on how the structure can be implemented by directly using a Binder instance] [仍在详细说明,将提供一个关于如何通过直接使用Binder实例来实现结构的方案]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.