Android 线程里发送广播必须等线程结束才能收到广播? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
doublemark
V2EX    Android

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

  •  
  •   doublemark 2019-02-01 16:08:07 +08:00 14610 次点击
    这是一个创建于 2510 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

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

    17 条回复    2019-02-02 15:21:38 +08:00
    momocraft
        1
    momocraft  
       2019-02-01 16:21:12 +08:00
    (在正确实现的时候)不是

    Java 有比较齐全的线程和同步 API,简单的比如 CountDownLatch / Future
    yippees
        2
    yippees  
       2019-02-01 17:30:09 +08:00
    1、activity 收发测试是 sendbraodcast 方法执行后 receiver 里收到,再等待结束。
    2、加个接收广播
    doublemark
        3
    doublemark  
    OP
       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
        4
    fuckshiter  
       2019-02-01 17:45:57 +08:00 via iPhone
    发送广播后。接收到广播做一个回调,或者用 eventbus 第三方库
    tempdban
        5
    tempdban  
       2019-02-01 17:46:33 +08:00 via Android
    我跟你说其实安卓的 activity 和 service 默认是跑在一个线程里的
    想这么干你要给 service 新建个线程
    这就是已经熟悉 Unix 变成的人必定踩坑点。
    yukiww233
        6
    yukiww233  
       2019-02-01 17:50:19 +08:00
    上 eventbus
    fuckshiter
        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"))
    }
    fuckshiter
        8
    fuckshiter  
       2019-02-01 18:01:24 +08:00 via iPhone
    @fuckshiter
    使用
    fun send() {
    sendCommand {
    doSomething1();
    doSomething2();
    doSomething3();
    }
    }
    yippees
        9
    yippees  
       2019-02-01 19:40:51 +08:00
    @doublemark
    我的代码也是 new thread 的
    只是接收也在 activity 就是。

    先打发日志,再打收日志,最后 sleep 结束日志
    richard1122
        10
    richard1122  
       2019-02-01 22:53:09 +08:00
    首先确认一下是真的开了新线程,是 thread.start() 而不是 thread.run() 了,后者会在当前线程直接执行这段代码。
    pagxir
        11
    pagxir  
       2019-02-01 23:17:31 +08:00
    你还是找个搞软件的来弄吧。你这是根本没有理解线程的概念。线程都 sleep 了,自然是不可能在去接收广播。
    receiver 的线程是运行在 handler 所在的线程。
    zpxshl
        12
    zpxshl  
       2019-02-02 09:38:35 +08:00 via Android
    不应该出现这种结果。我猜 10 楼说得对,你写成 new thread.run 。(应该调用 start 方法)
    至于楼上一堆说不能 sleep 的人是认真的吗。。。。
    SuperNovaSonic
        13
    SuperNovaSonic  
       2019-02-02 11:21:35 +08:00
    同意楼上,11 楼上来就乱说,楼主说的是 sleep 又不是让主线程 sleep
    SuperNovaSonic
        14
    SuperNovaSonic  
       2019-02-02 11:22:27 +08:00
    另外自己亲测了下,没有问题
    2019-02-02 11:19:11.790 14951-15076/com.example.glidetest D/BroadcastReceiveTest: new thread sendBroadcast
    2019-02-02 11:19:11.791 14951-15076/com.example.glidetest D/BroadcastReceiveTest: new thread try to sleep
    2019-02-02 11:19:11.805 14951-14951/com.example.glidetest D/BroadcastReceiveTest: BroadcastReceiver onReceive
    2019-02-02 11:19:14.793 14951-15076/com.example.glidetest D/BroadcastReceiveTest: new thread after sleep
    siyehua
        15
    siyehua  
       2019-02-02 13:48:49 +08:00
    发送广播不要建立线程。广播本身具有跨进程、线程的能力。直接根据需求发送与接收广播即可。使用到线程就必须用到线程消息同步的技术。
    RikkaW
        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 )就够了。
    ksssdh123
        17
    ksssdh123  
       2019-02-02 15:21:38 +08:00
    广播是一个很神奇的组件,跨线程,还跨进程
    如需求是需要跨进程,那就用起来吧
    如果用了 Rxjava,那么 Rxbus 用起来(也可以跨线程),如果没用 Rxjava 就 EventBus 应该满足你的需求了吧
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     4082 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 29ms UTC 05:33 PVG 13:33 LAX 21:33 JFK 00:33
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86