首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Android蓝牙:从UI线程启动的线程会阻塞UI线程

Android蓝牙:从UI线程启动的线程会阻塞UI线程
EN

Stack Overflow用户
提问于 2016-05-18 14:45:14
回答 2查看 860关注 0票数 2

我正在学习Android蓝牙编程。我从谷歌的Android开发者网站上复制了大部分代码以供学习。这个想法是监听服务器上的连接是在一个新的线程中完成的,而不会阻塞UI线程。当收到连接请求时,在另一个线程上完成连接,最后在另一个线程上完成通信。

问题是,当我从UI线程启动侦听线程时,它会自动阻塞,并且没有显示UI (冻结)。以下是示例代码:

代码语言:javascript
复制
public void onCreate(Bundle savedInstance) {
    super.onCreate(savedInstance);
    setContentView(R.layout.activity_main);
    ...

    badapter = BluetoothAdapter.getDefaultAdapter();
    if (badapter == null) {
        Toast.makeText(this, "No bluetooth device.", Toast.LENGTH_SHORT).show();
        return;
    }

    if (!badapter.isEnabled()) {
        Toast.makeText(this, "Bluetooth is disabled.", Toast.LENGTH_SHORT).show();
        return;
    }

    pairedDevices = new HashMap<String, String>();
    discoveredDevices = new HashMap<String, String>();

    showDevices();
    registerBroadcastReceiver();

    //this thread blocks UI thread
    ListenThread listen = new ListenThread();
    listen.run();
}

和监听线程:

代码语言:javascript
复制
public class ListenThread extends Thread {
    MainActivity main;
    CommunicateThread communicateThread;
    private final BluetoothServerSocket serverSocket;

    public ListenThread() {
        main = MainActivity.getInstance();

        BluetoothServerSocket tmp = null;
        try {
            tmp = main.badapter.listenUsingRfcommWithServiceRecord(main.NAME, main.MYUUID);
        } catch (final IOException e) {
            main.handler.post(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(main, "Error: " + e.getMessage(), Toast.LENGTH_LONG).show();
                }
            });
        }
        serverSocket = tmp;
    }

    public void run() {
        BluetoothSocket socket = null;

        //keep listening until exception occurs or a socket is returned
        while (true) {
            try {
                socket = serverSocket.accept();
            } catch (final IOException e) {
                main.handler.post(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(main, "Error: " + e.getMessage(), Toast.LENGTH_LONG).show();
                    }
                });
                break;
            }

            // If a connection was accepted
            if (socket != null) {
                //call communication thread once connection is established
                communicateThread = new CommunicateThread(socket);
                communicateThread.run();

                try {
                    serverSocket.close();
                } catch (final IOException e) {
                    main.handler.post(new Runnable() {
                        @Override
                        public void run() {
                            Toast.makeText(main, "Error: " + e.getMessage(), Toast.LENGTH_LONG).show();
                        }
                    });
                }
                break;
            }
        }
    }
}
EN

回答 2

Stack Overflow用户

发布于 2017-01-24 04:00:02

您在主线程上调用listen.run(),这使得它在主线程上运行。您应该调用listen.start(),它将派生一个单独的线程,在该线程中将执行run()方法。

提供给处理程序的Runnable将在主线程上执行,尽管handler用于主线程。

票数 2
EN

Stack Overflow用户

发布于 2017-01-24 03:45:23

我也有同样的问题。我所理解的是,每次你调用一个硬件,在这个例子中是蓝牙,你应该在另一个线程中进行。我将isEnabled()调用转移到其他线程,它解决了这个问题。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37292125

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档