Android Handler,在UI线程之外执行perform post()操作

8

从一开始我就认为Handler的方法post()postDelayed()在与UI线程不同的线程中执行,因此我决定在其中创建一个TCP Socket,但是它并没有起作用。

我收到了NetworkOnMainThreadException异常。

有没有办法在非UI线程中执行post()postDelayed()任务?

public class ServerHandler extends Handler {

private Socket serverSocket;   

public ServerHandler(){
    super(new MyHandlerThread("MyHandlerThread").getLooper());
}

@Override
public void handleMessage(Message msg) {
    super.handleMessage(msg);
}

public void connectServer()
{
    post(serverConnection);
}

public void writeMessage(String msg){
    try {
        serverSocket.getOutputStream().write(msg.getBytes());
        Log.d("MyLog","Message sent!");
    }
    catch (IOException io){
        Log.d("MyLog","SendMessage error");
    }
}

private Runnable serverConnection = new Runnable() {
    @Override
    public void run() {

        try {
            serverSocket = new Socket("152.168.21.24", 5001);

            Log.d("MyLog","Server connected!");

            while(true){
                Log.d("MyLog","Listening server");
                byte[] buffer = new byte[256];
                int bytesReceived = serverSocket.getInputStream().read(buffer);
                if(bytesReceived==-1) {
                    throw new IOException("Server disconnected");
                }
                else {
                  String msg = new String(buffer,0,bytesReceived);
                  Log.d("MyLog","Message received: " + msg);

                }
            }
        }

        catch (IOException io){
            Log.d("MyLog","Server connection error " + io.getMessage());
            connectServer();
        }
    }
};

}


使用BroadcastReceiver。百分之百有效。 - Mehran Zamani
您也可以实现EventBus库@http://greenrobot.org/eventbus/,以简化UI、异步和后台线程之间的通信。 - Dayan
你能分享一下你的代码吗? - hmartinezd
1个回答

5
Handler#post()方法可以在Looper线程中发布消息和运行任务。默认情况下,Handler的构造函数将绑定到创建它的Looper线程上。如果不在Looper线程上,则会抛出异常。因此,要在工作线程上使用Handler,您必须首先创建一个线程,并使用Looper循环它。然后将给定的Looper传递给Handler的构造函数。
幸运的是,已经有一个实用程序类可以为您完成大部分工作。它被称为HandlerThread。只需创建一个HandlerThread,并在需要该线程的Looper时调用getLooper即可。 编辑:默认的Handler构造函数不会选择主线程。如果当前线程已经是一个Looper线程,它会选择当前线程。

2
这里有一个使用HandlerThread的例子 - https://dev59.com/tF8f5IYBdhLWcg3wD-8v - Dayan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接