You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

线程运行时Android按钮onClick事件失效问题求助

问题分析与解决

你遇到的核心问题是主线程被无限循环阻塞了,导致UI完全无法响应(包括updateButton的点击事件)。

看一下你的run()方法:你用new Handler().post(new Runnable()把包含无限while(true)循环的逻辑放到了主线程执行。Android的主线程负责所有UI操作和事件响应,一旦被这种无限耗时操作占用,整个界面就会卡死,按钮点击、界面更新这些自然都没法正常工作了。

解决方案:把耗时操作放到子线程,主线程只处理UI/通信

正确的做法是把socket读取这种耗时逻辑放到独立的子线程里,主线程只负责接收子线程的消息并更新UI。下面是修正后的代码示例:

1. 修正线程执行逻辑

把你的run()方法改成这样,让socket读取在子线程跑:

public void startWeightReading() { // 换个更清晰的方法名
    new Thread(new Runnable() {
        @Override
        public void run() {
            int counter = 0;
            // 加个中断标志,方便后续停止线程
            while (!Thread.currentThread().isInterrupted()) {
                counter++;
                try {
                    String output = "";
                    if (mmInStream != null) {
                        int bytesRead = mmInStream.read(buffer); // 注意接收read的返回值,避免空读
                        if (bytesRead > 0) {
                            for (int i = 0; i < bytesRead; i++) {
                                char c = (char) buffer[i];
                                if (c >= ' ' && c < 'z') {
                                    output += c;
                                }
                            }
                        }
                        
                        if (counter % 10 == 0) {
                            System.out.println(counter);
                            // 用LocalBroadcast发送数据到主线程,和原来逻辑一致
                            Intent intent = new Intent("com.curie.WEIGHT_RECEIVED");
                            intent.putExtra("Output", output);
                            LocalBroadcastManager.getInstance(InputActivity.getContext())
                                .sendBroadcastSync(intent);
                        }
                    }
                    // 加个短延时,避免过度占用CPU
                    Thread.sleep(100);
                } catch (IOException e) {
                    e.printStackTrace();
                    break; // 连接断开,退出循环
                } catch (InterruptedException e) {
                    // 线程被中断,退出循环
                    Thread.currentThread().interrupt();
                    break;
                }
            }
        }
    }).start();
}

2. 修改按钮点击事件调用

在readWeight的点击事件里调用这个修正后的方法:

readWeight.setOnClickListener(new View.OnClickListener() {
    public void onClick(View v) {
        inputWindow.setText("helloooooooo worldddddd");
        System.out.println("********** PRINTING **********");
        // 启动子线程读取数据
        connector.startWeightReading();
        // readWeight.setVisibility(View.INVISIBLE);
    }
});

3. 额外注意事项

  • 线程中断:在Activity销毁时,记得中断这个子线程,避免内存泄漏。比如在onDestroy()里:
    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 如果你的connector持有线程引用,可以调用interrupt()
        // connector.weightReadingThread.interrupt();
    }
    
  • 避免空字符串拼接:每次读取socket数据时,先判断实际读取的字节数,不要直接遍历整个buffer,避免把空字节拼进去。
  • CPU占用优化:在循环里加个短延时(比如Thread.sleep(100)),避免子线程一直占用CPU资源。

这样修改后,主线程不会被阻塞,updateButton的点击事件就能正常响应了,同时socket读取也能在后台正常运行~

内容的提问来源于stack exchange,提问作者Collin Urie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:49:41