Search code examples
androidsocketsandroid-studioandroid-asynctasktcpclient

Asynctask cant display the server response


I created a socket program on android studio and I want to display the response of the server. The problem is when I'm using textResponse.setText(serverm); it didn't work. this is my code on asynctask

private class Connect extends AsyncTask<Void, Void, Void> {

    final String address = editTextAddress.getText().toString();


    String textResponse = null;
    String serverm = null;
    @Override
    protected Void doInBackground(Void... params) {
        mRun = true;

            try {
                client = new Socket(address, 3818);
                mBufferIn = new BufferedReader(new InputStreamReader(client.getInputStream()));


                while (mRun) {
                    serverm = mBufferIn.readLine();

                    if (serverm != null) {
                        System.out.println(serverm);
                        textResponse.setText(serverm);


                    }
                }
            } catch (UnknownHostException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        return null;
    }

}                 

Solution

  • What's (Likely) Wrong

    It looks like you are trying to continuously poll a server and update a text field. An AsyncTask is probably not the best choice of tools to achieve this. The typical use case for AsyncTasks is that you have a single piece of work that will take a long time, and you want to update the UI when it's done.

    The (probable) reason your code isn't working is because the AsyncTask's doInBackground method is being run on a background thread but you are trying to update the UI textResponse.setText(serverm). On Android, all updates to UI elements have to happen on the "main" or "UI" thread. Your code is likely throwing an exception on this line and killing the AsyncTask.

    Suggestion

    I think a simple background thread along with posting to the UI thread when you have updates would be a more natural fit. With this scheme you have a long living thread that you can perform your networking on that will schedule work to be done on the UI thread when updates need to happen to the UI.

    // Create an android.os.Handler that you can use to post Runnables 
    // to the UI thread.
    private static final Handler UI_HANDLER = new Handler(Looper.getMainLooper());
    
    // Create a Runnable that will poll a server and send updates to the
    // UI thread.
    private final Thread mConnectAndPoll = new Thread(new Runnable() {
    
        @Override
        public void run() {
            mRun = true;
            try {
                String address = editTextAddress.getText().toString();
                client = new Socket(address, 3818);
                mBufferIn = new BufferedReader(
                        new InputStreamReader(client.getInputStream()));
    
                while (mRun) {
                    serverm = mBufferIn.readLine();
    
                    if (serverm != null) {
                        System.out.println(serverm);
                        // Create a Runnable that will update the 
                        // textResponse TextView with the response from
                        // the server, and schedule it to run on the UI 
                        // thread.
                        UI_HANDLER.post(new UpdateResponseRunnable(serverm));
                    }
                }
            } catch (UnknownHostException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    });
    
    // Create a subclass of Runnable that will update textResponse.
    private class UpdateResponseRunnable implements Runnable {
        private final String mValue;
    
        public UpdateResponseRunnable(String value) {
            mValue = value;
        }
    
        @Override
        public void run() {
            textResponse.setText(mValue);
        }
    };
    
    // Start the background thread in onCreate or wherever you are
    // currently starting your AsyncTask.
    @Override
    public void onCreate(Bundle bundle) {
        super.onCreate(bundle);
    
        mConnectAndPoll.start();
    }