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

时间:2015-01-09 16:15:27

标签: java android ipc aidl

场景:我有一个Controller(普通的Java类),必须能够试用几个Slave

Slave的性质可能不同,因此它可以是:

  1. A Service,我们称之为ServiceSlave:此对象的生命周期通常与应用程序的组件不同(例如,它不依赖于当前活动)
  2. 一个简单的Java类,比如说ObjectSlave:这个对象的生命周期在某种程度上与创建它的范围有关(比如当前活动)
  3. 这两种Slave的共同之处在于它们可以驻留在不同的流程中


    由于最后一个“要求”,我立即将注意力转移到AIDL / Messenger作为ControllerSlave之间的沟通形式,因为它提供IPC。

    但是,似乎AIDL(反过来Messenger,因为它也应该基于AIDL)只有在你使用{{1}时才会定义 }} 即可。也就是说,我没有办法在没有Service对象的情况下实现基于AIDL的接口,这通常在IBinder方法中提供。

    第一个问题:只有在处理onServiceConnected时才能真正使用AIDL吗?如果是,为什么呢?

    现在,考虑一下我的情景。正如任何其他优秀的开发人员所希望的那样,我希望编写一个优雅的界面,允许Service试用每个Controller,无论其性质如何。到目前为止,我想到的唯一解决方案是使用SlaveIntent,它们都可以方便地包装在专用的Java类中。

    第二个问题:这是唯一可行的方法吗?我在监督什么吗?


    修改

    我想我应该提供有关BroadcastReceiver元素实际执行内容的更多详细信息。它是一个与几个UI小部件松散耦合的组件,他们订阅了它。它已被设计(自愿),因此它不需要引用Controller。因此它不直接需要使用 UI小部件,但反过来这些小部件依赖于Context

2 个答案:

答案 0 :(得分:4)

这是一个很好但不是一个简单的问题。像大多数事情一样,有多种方法可以解决这类问题。首先要检查的是Controller是否需要或使用UI组件。如果没有,那么您需要将其封装在Service中。 Activity生命周期只有当它是屏幕上的当前内容时才会运行。一旦用户按下HOME或BACK,它就会分别停止或销毁。通过通知或在您的应用内启动另一个应用将产生类似于按HOME的效果:您的Activity将暂停。

因此,假设您不需要/想要Controller的用户界面,那么您可以使用大量的内容:

  1. 通过公开自定义AIDL界面,使您的服务成为“绑定”服务。不难,但也不是因为佯装。
  2. 让您的服务回复自定义Intent以采取某些措施。然后,Service可以重新启动广播或启动特定的“奴隶”Activity。如果对此感兴趣,请探索使用IntentService来更好地管理线程并防止您的应用出现ANR。
  3. 与上一个相似,使用自定义Intent并让您的奴隶在Messenger内发送一个Intent对象,作为额外内容。此时,Service可以向Messenger发送消息,该消息由从属Activity拥有,并将发送给特定的Handler
  4. 您不需要为选项2和3提供自定义AIDL公开接口。您是正确的,如果要使用绑定服务并且Service.onBind()方法必须返回实例,则必须定义AIDL接口您的活页夹接口存根实现。

    所有这些,您可以使用这三种方法中的任何一种来实现您使用驻留在ActivityService实例中的从属类的目标。使用AIDL或Messenger方法的优点是减少了上下文切换(更高效),因为您没有发送Intent个对象。每次发送Intent时,发件人都会联系系统进程中运行的ActivityManagerService,以解决Intent的投放位置。使用AIDL和Messenger,只有最初的bindService()startService()来电可以与ActivityManagerService联系。在此之后,使用两个进程之间的直接绑定器执行通信。

答案 1 :(得分:2)

结果AIDLBinderService无关。

虽然只有在绑定到IBinder时才提供Service引用,但框架提供了Binder类,它已经实现了IBinder接口。

此外,Binder实例跨进程透明地工作,并且不需要生活在Service上下文中。


[仍然详细说明,将提供一个关于如何通过直接使用Binder实例来实现结构的方案]