Android的BroadcastReceiver还是简单的callback方法?
在我的项目中,我使用BroadcastReceiver
作为长时间运行的线程的callback(例如,通知活动下载已完成,并从Worker Thread
发送一些响应数据,以便活动可以向用户显示相应的消息。 )。 要使用BroadcastReceiver
我必须小心地注册和注销广播接收器,每次我使用它时,还必须关心什么消息发送esspecialy当我使用这种方法更多不同的行动(如下载,使WebService调用等等..)。 也通过广播的意图发送自定义对象我还需要使对象Parcelable
。
与这种方法不同的是,我也看到了callback方法,它似乎比我使用的方法简单。 callback方法是简单的接口方法的实现,可以用来实现像应用程序消息传递中的BroadcastRecaiver一样的效果。 这种方法并不需要Parcelable实现来返回复杂的对象,它不使用像BroadcastReceiver
这样的键。我认为不好的部分是,我需要检查callback对象的空值,然后再调用callback方法。并确保我正在UI线程上执行的代码,以便我可以更新UI没有错误。
好吧,我希望你明白我的意思是说:)。
现在的问题是你认为callback方法比单纯使用单一应用程序时的BroadcastReceiver
方法更好(更轻,更干净,更快..)吗? (请注意,我不使用Android Service
的后台工作..只是AsyncTask
和Thread
)
谢谢!
这是一个非常有趣的问题,我遇到了同样的问题。 在我看来,这两种机制可以一起使用,正确的使用方法取决于您的使用情况。 在决定之前,请注意以下几点。
使用callback机制有一些好处,但也有一些限制:
PRO
- 实施简单直接。
- 您在彼此交互的组件之间获得types安全性。
- 你可以返回任意对象。
- 它简化了testing,因为您只需在unit testing中注入模拟callback(例如通过mockito或类似的东西生成)。
魂斗罗
- 你必须切换到主线程才能进行UI操作。
- 你只能有1对1的关系。 一对一的关系(观察者模式)是不能实现的,没有进一步的工作。 在这种情况下,我更喜欢Android的
Observer
/Observable
机制。 - 正如你已经说过的,如果callback可能是可选的,你必须在调用callback函数之前检查
null
。 - 如果你的组件应该提供一种具有不同服务function的服务API,并且你不想只有一些通用callback函数的callback接口,那么你必须决定是否为每个服务函数提供一个特殊的callback接口,或者你是否提供了一个callback函数的callback接口。 在后面的情况下,用于服务调用API的所有callback客户端都必须实现完整的callback接口,尽pipe大部分方法体将是空的。 你可以通过实现一个存根为空的存根,并使得你的callback客户端inheritance这个存根,但是如果它已经从另一个基类inheritance,这是不可能的。 也许你可以使用某种dynamic代理callback(请参阅http://developer.android.com/reference/java/lang/reflect/Proxy.html ),但是这会变得非常复杂,我会考虑使用另一种机制。
- 如果服务的调用者不能直接访问,callback调用的客户端必须通过各种方法/组件传播。
关于BroadcastReceiver
接收机的一些观点 – 方法:
PRO
- 实现组件之间的松散耦合。
- 你可以有一对一的关系(包括1对0)。
-
onReceive()
方法总是在主线程上执行。 - 您可以通知整个应用程序中的组件,因此通信组件不必“看见”彼此。
魂斗罗
- 这是一个非常通用的方法,因此
Intent
传输的数据的编组和非标记是另一个错误源。 - 如果您想要消除与其他应用程序的关联,则必须使您的
Intent
的操作具有唯一性(例如通过预先包装名称),因为它们的最初目的是在应用程序之间进行广播。 - 您必须pipe理BroadcastReceiver注册和注销。 如果您想以更舒适的方式执行此操作,则可以实现一个自定义注释,以便使用应该注册的操作对注释进行注释,并实现一个基本的
Activity
类,该类将在其onResume()
使用IntentFilter
注册和注销。onPause()
方法。 - 正如你所说的,与
Intent
一起发送的数据必须实现Parcelable
接口,但是还存在严格的大小限制,如果你用Intent
传输大量的数据,会导致性能问题。 有关这方面的讨论,请参阅http://code.google.com/p/android/issues/detail?id=5878 。 因此,如果您想发送图像,例如您必须将其临时存储在存储库中,并发送相应的ID或URL以访问Intent
的接收器中的图像,并在使用后将其从存储库中删除。 如果有多个接收器(如何将图像从存储库中删除以及谁应该这样做?),则会导致进一步的问题。 - 如果过度使用这种通知机制,则应用程序的控制stream可能会被隐藏起来,而在debugging时,最终会绘制带有
Intent
序列的图表,以了解触发了特定错误的是什么,或者为什么这个通知链在某些时候被打断。
在我看来,即使是移动应用程序也应该有一个基于至less2层的架构:UI层和核心层(带有业务逻辑等)。 一般来说,长时间运行的任务在核心层内的一个自己的线程中执行(可能通过AsyncTask
或HandlerThread
),并且在任务完成后应该更新UI。 一般情况下,通过callback可以实现组件之间的紧密耦合,所以我宁愿只在一个图层中使用这种方法,而不是跨层边界进行通信。 对于在UI和核心层之间的消息广播,我会使用BroadcastReceiver
方法,它可以让你的UI层和逻辑层分离。
在您的情况下,我看不到您使用BroadcastReceiver
获得的收益。 callback或更可能的, Handlers
将是做到这一点。 当你不知道用户是谁的时候BroadcastReceiver
是好的。
我只是添加另一个选项,您已经收到其他伟大的答案…
您不必创build广播接收器来接收Intents。 在你的Android清单文件中,你可以注册任何活动来接收意图:
<activity android:name=".MyActivity"> <intent-filter > <action android:name="intent.you.want.to.receive" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> .... </activity>
然后覆盖活动中的onNewIntent(Intent)
方法以接收它。
要发送意图,请使用Context.startActivity(Intent)
方法。 最有可能的是,您需要将FLAG_ACTIVITY_SINGLE_TOP
标志添加到您的Intent中,以便在已经运行的情况下不会创build活动的新实例。
编辑:我只注意到你正在一个单一的应用程序内运行。 因此,一个简单的callback可能是最好的。 上面的解决scheme在单个应用程序中工作,但更适合不同的应用程序。 我会在这里留下,以防万一它帮助某人。 祝你好运!
应该使用广播接收器如果您需要跨应用程序发送广播,而callback(或Alexbuild议的处理程序)更适合您的情况。
如果你想使用比这两个以外,考虑使用Observer (包含在android中的接口)和委托。
对于代表请考虑这个 SOpost。
希望这会解决你的问题
不知道目标是什么,但如果你想保持使用intent和broadcastReceiver相同的想法,并希望比正常的broadcastReceivers更好的性能和安全性,你可以尝试这个演示,可在android支持库:
如果没有,你总是可以使用asyncTask,服务,处理程序等…