Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android handler, perform post() not in the ui thread

From the beginning I though Handler's methods post() and postDelayed() did things in a different thread from UI thread, and I decided to create a TCP Socket on it, but it's not working.

I'm receiving NetworkOnMainThreadException was thrown.

Is there any ways to perform post() and postDelayed() tasks not in the UI thread?

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();
        }
    }
};

}

like image 861
Isen Avatar asked Feb 27 '17 16:02

Isen


1 Answers

Handler#post() posts Messages and Runnables on Looper threads. The default constructor of a Handler will bind itself to the Looper thread that it was created on. If it's not on a Looper thread, then it'll throw an exception. So, to use a Handler on a worker thread, you must first create a thread and loop it with a Looper. Then you pass the given Looper to the Handler's constructor.

Fortunately, there's already a utility class that does most of the work for you. It's called HandlerThread. Just create a HandlerThread, and call getLooper whenever you need the Looper for the thread.

EDIT: Default Handler constructor does not choose the main thread. It chooses the current thread if it's a Looper thread already.

like image 191
DeeV Avatar answered Oct 22 '22 20:10

DeeV