原谅我是一个硬件工程师,最近在做一个和硬件相关的测试软件,大部分功能都已实现,目前问题是: 在 C++里可以在线程里发送指令,然后 sleep 一段时间用以等待返回的数据,而 android 里想用同样的思路: 1、通讯封装在了一个 Service 里保持后台运行; 2、在按钮点击事件里按下按钮后新建 Thread,线程里发送广播到 Service,Service 里根据广播里的参数去执行相应的发送命令,并在 Service 里做接收解析,若解析正确则置一标志位。 3、2 里提到的线程在发送完广播后,sleep 一段时间等待该标志位,若标志位成立则继续往下执行,以此类推。 目前问题就在于: 2 里在 Thread 里发送广播,根据调试以及 log 看,并不是在 sendbraodcast 方法执行后再 receiver 里收到,而是该 Thread 执行完之后才会收到,这样是正常的吗?
对于这种需要执行多个步骤的耗时和等待操作,在 Android 里有没有好的方案?
感谢各位,很荣幸能来到这里。
1
momocraft 2019-02-01 16:21:12 +08:00
(在正确实现的时候)不是
Java 有比较齐全的线程和同步 API,简单的比如 CountDownLatch / Future |
2
yippees 2019-02-01 17:30:09 +08:00
1、activity 收发测试是 sendbraodcast 方法执行后 receiver 里收到,再等待结束。
2、加个接收广播 |
3
doublemark OP @yippees 实际使用中确实是在 sendbroadcast 之后在 receiver 里能收到,但是一放到 thread 里
{ sendbroadcast(intent); try { sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } dosomethingA(); dosomethingB(); dosomethingC(); } 在这里,sendbroadcast 方法执行后并没有收到,反而是 dosomethingC 之后才收到。奇怪啊。 |
4
fuckshiter 2019-02-01 17:45:57 +08:00 via iPhone
发送广播后。接收到广播做一个回调,或者用 eventbus 第三方库
|
5
tempdban 2019-02-01 17:46:33 +08:00 via Android
我跟你说其实安卓的 activity 和 service 默认是跑在一个线程里的
想这么干你要给 service 新建个线程 这就是已经熟悉 Unix 变成的人必定踩坑点。 |
6
yukiww233 2019-02-01 17:50:19 +08:00
上 eventbus
|
7
fuckshiter 2019-02-01 17:58:52 +08:00 via iPhone
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")) } |
8
fuckshiter 2019-02-01 18:01:24 +08:00 via iPhone
|
9
yippees 2019-02-01 19:40:51 +08:00
|
10
richard1122 2019-02-01 22:53:09 +08:00
首先确认一下是真的开了新线程,是 thread.start() 而不是 thread.run() 了,后者会在当前线程直接执行这段代码。
|
11
pagxir 2019-02-01 23:17:31 +08:00
你还是找个搞软件的来弄吧。你这是根本没有理解线程的概念。线程都 sleep 了,自然是不可能在去接收广播。
receiver 的线程是运行在 handler 所在的线程。 |
12
zpxshl 2019-02-02 09:38:35 +08:00 via Android
不应该出现这种结果。我猜 10 楼说得对,你写成 new thread.run 。(应该调用 start 方法)
至于楼上一堆说不能 sleep 的人是认真的吗。。。。 |
13
SuperNovaSonic 2019-02-02 11:21:35 +08:00
同意楼上,11 楼上来就乱说,楼主说的是 sleep 又不是让主线程 sleep
|
14
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 |
15
siyehua 2019-02-02 13:48:49 +08:00
发送广播不要建立线程。广播本身具有跨进程、线程的能力。直接根据需求发送与接收广播即可。使用到线程就必须用到线程消息同步的技术。
|
16
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 )就够了。 |
17
ksssdh123 2019-02-02 15:21:38 +08:00
广播是一个很神奇的组件,跨线程,还跨进程
如需求是需要跨进程,那就用起来吧 如果用了 Rxjava,那么 Rxbus 用起来(也可以跨线程),如果没用 Rxjava 就 EventBus 应该满足你的需求了吧 |