Android 线程里发送广播必须等线程结束才能收到广播?

2019-02-01 16:08:07 +08:00
 doublemark

原谅我是一个硬件工程师,最近在做一个和硬件相关的测试软件,大部分功能都已实现,目前问题是: 在 C++里可以在线程里发送指令,然后 sleep 一段时间用以等待返回的数据,而 android 里想用同样的思路: 1、通讯封装在了一个 Service 里保持后台运行; 2、在按钮点击事件里按下按钮后新建 Thread,线程里发送广播到 Service,Service 里根据广播里的参数去执行相应的发送命令,并在 Service 里做接收解析,若解析正确则置一标志位。 3、2 里提到的线程在发送完广播后,sleep 一段时间等待该标志位,若标志位成立则继续往下执行,以此类推。 目前问题就在于: 2 里在 Thread 里发送广播,根据调试以及 log 看,并不是在 sendbraodcast 方法执行后再 receiver 里收到,而是该 Thread 执行完之后才会收到,这样是正常的吗?

对于这种需要执行多个步骤的耗时和等待操作,在 Android 里有没有好的方案?

感谢各位,很荣幸能来到这里。

11620 次点击
所在节点    Android
17 条回复
momocraft
2019-02-01 16:21:12 +08:00
(在正确实现的时候)不是

Java 有比较齐全的线程和同步 API,简单的比如 CountDownLatch / Future
yippees
2019-02-01 17:30:09 +08:00
1、activity 收发测试是 sendbraodcast 方法执行后 receiver 里收到,再等待结束。
2、加个接收广播
doublemark
2019-02-01 17:42:43 +08:00
@yippees 实际使用中确实是在 sendbroadcast 之后在 receiver 里能收到,但是一放到 thread 里
{
sendbroadcast(intent);
try {
sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
dosomethingA();
dosomethingB();
dosomethingC();
}
在这里,sendbroadcast 方法执行后并没有收到,反而是 dosomethingC 之后才收到。奇怪啊。
fuckshiter
2019-02-01 17:45:57 +08:00
发送广播后。接收到广播做一个回调,或者用 eventbus 第三方库
tempdban
2019-02-01 17:46:33 +08:00
我跟你说其实安卓的 activity 和 service 默认是跑在一个线程里的
想这么干你要给 service 新建个线程
这就是已经熟悉 Unix 变成的人必定踩坑点。
yukiww233
2019-02-01 17:50:19 +08:00
上 eventbus
fuckshiter
2019-02-01 17:58:52 +08:00
class FooBroadcastReceiver(var callback: () -> Unit) : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
when (intent?.action) {
"XXXXACTION" -> {
callback();
}
}
}
}

var fooBroadcastReceiver: FooBroadcastReceiver? = null
fun sendCommand(callback: () -> Unit) {
fooBroadcastReceiver = fooBroadcastReceiver ?: FooBroadcastReceiver(callback)
fooBroadcastReceiver?.callback = callback
mContext.sendBroadcast(Intent("XXXXACTION"))
}
fuckshiter
2019-02-01 18:01:24 +08:00
@fuckshiter
使用
fun send() {
sendCommand {
doSomething1();
doSomething2();
doSomething3();
}
}
yippees
2019-02-01 19:40:51 +08:00
@doublemark
我的代码也是 new thread 的
只是接收也在 activity 就是。

先打发日志,再打收日志,最后 sleep 结束日志
richard1122
2019-02-01 22:53:09 +08:00
首先确认一下是真的开了新线程,是 thread.start() 而不是 thread.run() 了,后者会在当前线程直接执行这段代码。
pagxir
2019-02-01 23:17:31 +08:00
你还是找个搞软件的来弄吧。你这是根本没有理解线程的概念。线程都 sleep 了,自然是不可能在去接收广播。
receiver 的线程是运行在 handler 所在的线程。
zpxshl
2019-02-02 09:38:35 +08:00
不应该出现这种结果。我猜 10 楼说得对,你写成 new thread.run 。(应该调用 start 方法)
至于楼上一堆说不能 sleep 的人是认真的吗。。。。
SuperNovaSonic
2019-02-02 11:21:35 +08:00
同意楼上,11 楼上来就乱说,楼主说的是 sleep 又不是让主线程 sleep
SuperNovaSonic
2019-02-02 11:22:27 +08:00
另外自己亲测了下,没有问题
2019-02-02 11:19:11.790 14951-15076/com.example.glidetest D/BroadcastReceive Test: new thread sendBroadcast
2019-02-02 11:19:11.791 14951-15076/com.example.glidetest D/BroadcastReceive Test: new thread try to sleep
2019-02-02 11:19:11.805 14951-14951/com.example.glidetest D/ BroadcastReceive Test: BroadcastReceiver onReceive
2019-02-02 11:19:14.793 14951-15076/com.example.glidetest D/BroadcastReceive Test: new thread after sleep
siyehua
2019-02-02 13:48:49 +08:00
发送广播不要建立线程。广播本身具有跨进程、线程的能力。直接根据需求发送与接收广播即可。使用到线程就必须用到线程消息同步的技术。
RikkaW
2019-02-02 14:20:44 +08:00
sendBroadcast 实际是“自己的应用进程到 system_server 进程,再到目标进程”这样一个比较重的过程(因为本来就是设计用来跨进程广播的),用在这里就过于夸张了。(所以可能是 sleep 时间太短了正好就看起来更晚收到?)另外发广播并不需要建立线程,因为只有把 intent 发给 system_server 的过程。
这里的情况看起来只要用 LocalbroadcastManager EventBus 这样的或是绑定服务( https://developer.android.com/guide/components/bound-services )就够了。
ksssdh123
2019-02-02 15:21:38 +08:00
广播是一个很神奇的组件,跨线程,还跨进程
如需求是需要跨进程,那就用起来吧
如果用了 Rxjava,那么 Rxbus 用起来(也可以跨线程),如果没用 Rxjava 就 EventBus 应该满足你的需求了吧

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/532473

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX