简体   繁体   English

为什么AIDL / Messenger绑定到服务?

[英]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的本性可以有所不同,因此它可以是:

  1. A 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 :该对象的生命周期通常不同于应用程序的组件(例如,它不依赖于当前活动)
  2. A simple Java class, say a ObjectSlave : the lifecycle of this object is somewhat bound to the scope in which it is created (say, the current activity) 一个简单的Java类,比如说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作为ControllerSlave之间的通信形式,因为它提供了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. 到目前为止,我想到的唯一解决方案是使用IntentBroadcastReceiver ,它们都可以方便地包含在专用的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,您可以使用大量的东西:

  1. Make your service a "bound" service by exposing a custom AIDL interface. 通过公开自定义AIDL接口使您的服务成为“绑定”服务。 Not difficult, but not for the feint of heart either. 不难,但也不是因为佯攻。
  2. Make your service respond to custom 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。
  3. Similar to the previous, use a custom 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种方法中的任何一种来实现使用驻留在ActivityService实例中的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. 事实证明AIDLBinderService无关。

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM