Is using AsyncTask in a multi-user chat Android client better than extending a connection thread?












0














I'm practicing multi-client networking using a Java Server and Android clients. I have done this with Java clients before so I adapted my solution mostly around what I know in Java using multithreading. Which is extending a thread for each client connection created. I usually have a separate ClientConnection class in Java but here I used a protected inner class.



This solution works but someone mentioned to me that I might want to do this with AsyncTask rather. What benefits would using AsyncTask offer rather than extending a thread the way I have done here?



Please note I am not asking for any code or how I would go about doing it. Just what benefits it would offer over this method.



Client Layout



<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context="za.ac.nmu.wrap302.jan2015.MainActivity">

<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/loginPanel"
android:layout_alignParentBottom="true">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/etHandle"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Connect"
android:id="@+id/btnConnect"
android:layout_below="@+id/etHandle"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignRight="@+id/etHandle"
android:layout_alignEnd="@+id/etHandle"/>
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/chatPanel"
android:visibility="gone">
<ListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/lvMessages"
android:layout_below="@+id/btnConnect"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_above="@+id/txtMessage"/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Change Room"
android:id="@+id/btnRoom"/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/txtMessage"
android:layout_above="@+id/btnDisconnect"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignRight="@+id/btnDisconnect"
android:layout_alignEnd="@+id/btnDisconnect"/>
</LinearLayout>
<LinearLayout
android:background="?android:colorBackground"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/roomPanel"
android:visibility="gone">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Disconnect"
android:id="@+id/btnDisconnect"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignRight="@+id/lvMessages"
android:layout_alignEnd="@+id/lvMessages"/>
<ListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/lvRooms"/>
</LinearLayout>




Client Code



public class MainActivity extends AppCompatActivity {
EditText etHandle;
ConnectionThread connectionThread;
private ArrayList<String> messages;
private ArrayAdapter<String> adapter;

private ArrayList<String> rooms;
private ArrayAdapter<String> roomsAdapter;

private static final String SET_HANDLE = "#SetHandle";
private static final String SEND_MESSAGE = "#SendMessage";
private static final String DISCONNECT = "#Disconnect";
private static final String JOIN_ROOM = "#JoinRoom";
private static final String LIST_ROOMS = "#ListRooms";

ListView lvMessages;
ListView lvRooms;

EditText textMessage;
Button btnConnect;
Button btnDisconnect;
Button btnRoom;
LinearLayout chatPanel, roomPanel, loginPanel;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

etHandle = (EditText) findViewById(R.id.etHandle);
lvMessages = (ListView) findViewById(R.id.lvMessages);
textMessage = (EditText) findViewById(R.id.txtMessage);
btnConnect = (Button) findViewById(R.id.btnConnect);
btnDisconnect = (Button) findViewById(R.id.btnDisconnect);
chatPanel = (LinearLayout) findViewById(R.id.chatPanel);
roomPanel = (LinearLayout) findViewById(R.id.roomPanel);
loginPanel = (LinearLayout) findViewById(R.id.loginPanel);
lvRooms = (ListView) findViewById(R.id.lvRooms);
btnRoom = (Button) findViewById(R.id.btnRoom);

messages = new ArrayList<String>();
adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_selectable_list_item, messages);
lvMessages.setAdapter(adapter);

rooms = new ArrayList<String>();
roomsAdapter = new ArrayAdapter<String>(this,
android.R.layout.simple_selectable_list_item, rooms);
lvRooms.setAdapter(roomsAdapter);

btnConnect.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
connectionThread = new ConnectionThread(etHandle.getText().toString());
connectionThread.start();
}
});

btnDisconnect.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Thread out = new Thread(new Runnable() {
@Override
public void run() {
try {
connectionThread.out.writeUTF(DISCONNECT);
} catch (IOException e) {
e.printStackTrace();
}
}
});
out.start();
hideRoomScreen();
showLoginScreen();
}
});

btnRoom.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
showRoomScreen();
Thread out = new Thread(new Runnable() {
@Override
public void run() {
try {
connectionThread.out.writeUTF(LIST_ROOMS);
} catch (IOException e) {
e.printStackTrace();
}
}
});
out.start();
}
});

textMessage.setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_ENTER) && (event.getAction() == KeyEvent.ACTION_DOWN)) {
final String text = textMessage.getText().toString();
Thread out = new Thread(new Runnable() {
@Override
public void run() {
try {
connectionThread.out.writeUTF(SEND_MESSAGE);
connectionThread.out.writeUTF(text);
} catch (IOException e) {
e.printStackTrace();
}
}
});
out.start();
textMessage.getText().clear();
return true;
}
return false;
}
});

lvRooms.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
final String roomName = roomsAdapter.getItem(i);
Thread out = new Thread(new Runnable() {
@Override
public void run() {
try {
connectionThread.out.writeUTF(JOIN_ROOM);
connectionThread.out.writeUTF(roomName);
} catch (IOException e) {
e.printStackTrace();
}
}
});
out.start();
hideRoomScreen();
showChatScreen();
}
});
}

public void addMessage(String message) {
adapter.add(message);
lvMessages.setSelection(adapter.getCount() - 1);
}

public void addRoom(final String roomName){
runOnUiThread(new Runnable() {
@Override
public void run() {
roomsAdapter.add(roomName);
}
});
}

protected class ConnectionThread extends Thread {
Socket connection;
DataInputStream in;
DataOutputStream out;
String handle;
boolean connected;

public ConnectionThread(String name) {
handle = name;
}

@Override
public void run() {
try {
connection = new Socket("10.0.0.10", 1234);
connected = true;

in = new DataInputStream(connection.getInputStream());
out = new DataOutputStream(connection.getOutputStream());

out.writeUTF(handle);

hideLoginScreen();
btnRoom.callOnClick();

String command = "";
while (connected) {
command = in.readUTF();
switch (command) {
case SEND_MESSAGE:
final String user = in.readUTF();
final String message = in.readUTF();
runOnUiThread(new Runnable() {
@Override
public void run() {
addMessage(user + ": " + message);
}
});
break;
case DISCONNECT:
showLoginScreen();
connected = false;
break;
case LIST_ROOMS:
int count = in.readInt();
runOnUiThread(new Runnable() {
@Override
public void run() {
roomsAdapter.clear();
}
});
for(int i = 0; i < count; i++){
String roomName = in.readUTF();
addRoom(roomName);
}
break;
}
}

} catch (IOException e) {
e.printStackTrace();
}

}
}

private void showLoginScreen() {
runOnUiThread(new Runnable() {
@Override
public void run() {
loginPanel.setVisibility(View.VISIBLE);
}
});
}

private void hideLoginScreen() {
runOnUiThread(new Runnable() {
@Override
public void run() {
loginPanel.setVisibility(View.GONE);
}
});
}

private void showChatScreen() {
runOnUiThread(new Runnable() {
@Override
public void run() {
chatPanel.setVisibility(View.VISIBLE);
}
});
}

private void hideChatScreen() {
runOnUiThread(new Runnable() {
@Override
public void run() {
chatPanel.setVisibility(View.GONE);
}
});
}

private void showRoomScreen() {
runOnUiThread(new Runnable() {
@Override
public void run() {
roomPanel.setVisibility(View.VISIBLE);
}
});
}

private void hideRoomScreen() {
runOnUiThread(new Runnable() {
@Override
public void run() {
roomPanel.setVisibility(View.GONE);
}
});
}


}










share|improve this question



























    0














    I'm practicing multi-client networking using a Java Server and Android clients. I have done this with Java clients before so I adapted my solution mostly around what I know in Java using multithreading. Which is extending a thread for each client connection created. I usually have a separate ClientConnection class in Java but here I used a protected inner class.



    This solution works but someone mentioned to me that I might want to do this with AsyncTask rather. What benefits would using AsyncTask offer rather than extending a thread the way I have done here?



    Please note I am not asking for any code or how I would go about doing it. Just what benefits it would offer over this method.



    Client Layout



    <RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context="za.ac.nmu.wrap302.jan2015.MainActivity">

    <LinearLayout
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/loginPanel"
    android:layout_alignParentBottom="true">
    <EditText
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/etHandle"
    android:layout_alignParentTop="true"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true"
    android:layout_alignParentRight="true"
    android:layout_alignParentEnd="true"/>
    <Button
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="Connect"
    android:id="@+id/btnConnect"
    android:layout_below="@+id/etHandle"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true"
    android:layout_alignRight="@+id/etHandle"
    android:layout_alignEnd="@+id/etHandle"/>
    </LinearLayout>
    <LinearLayout
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/chatPanel"
    android:visibility="gone">
    <ListView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/lvMessages"
    android:layout_below="@+id/btnConnect"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true"
    android:layout_above="@+id/txtMessage"/>
    <Button
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="Change Room"
    android:id="@+id/btnRoom"/>
    <EditText
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/txtMessage"
    android:layout_above="@+id/btnDisconnect"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true"
    android:layout_alignRight="@+id/btnDisconnect"
    android:layout_alignEnd="@+id/btnDisconnect"/>
    </LinearLayout>
    <LinearLayout
    android:background="?android:colorBackground"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/roomPanel"
    android:visibility="gone">
    <Button
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="Disconnect"
    android:id="@+id/btnDisconnect"
    android:layout_alignParentBottom="true"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true"
    android:layout_alignRight="@+id/lvMessages"
    android:layout_alignEnd="@+id/lvMessages"/>
    <ListView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/lvRooms"/>
    </LinearLayout>




    Client Code



    public class MainActivity extends AppCompatActivity {
    EditText etHandle;
    ConnectionThread connectionThread;
    private ArrayList<String> messages;
    private ArrayAdapter<String> adapter;

    private ArrayList<String> rooms;
    private ArrayAdapter<String> roomsAdapter;

    private static final String SET_HANDLE = "#SetHandle";
    private static final String SEND_MESSAGE = "#SendMessage";
    private static final String DISCONNECT = "#Disconnect";
    private static final String JOIN_ROOM = "#JoinRoom";
    private static final String LIST_ROOMS = "#ListRooms";

    ListView lvMessages;
    ListView lvRooms;

    EditText textMessage;
    Button btnConnect;
    Button btnDisconnect;
    Button btnRoom;
    LinearLayout chatPanel, roomPanel, loginPanel;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    etHandle = (EditText) findViewById(R.id.etHandle);
    lvMessages = (ListView) findViewById(R.id.lvMessages);
    textMessage = (EditText) findViewById(R.id.txtMessage);
    btnConnect = (Button) findViewById(R.id.btnConnect);
    btnDisconnect = (Button) findViewById(R.id.btnDisconnect);
    chatPanel = (LinearLayout) findViewById(R.id.chatPanel);
    roomPanel = (LinearLayout) findViewById(R.id.roomPanel);
    loginPanel = (LinearLayout) findViewById(R.id.loginPanel);
    lvRooms = (ListView) findViewById(R.id.lvRooms);
    btnRoom = (Button) findViewById(R.id.btnRoom);

    messages = new ArrayList<String>();
    adapter = new ArrayAdapter<String>(this,
    android.R.layout.simple_selectable_list_item, messages);
    lvMessages.setAdapter(adapter);

    rooms = new ArrayList<String>();
    roomsAdapter = new ArrayAdapter<String>(this,
    android.R.layout.simple_selectable_list_item, rooms);
    lvRooms.setAdapter(roomsAdapter);

    btnConnect.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
    connectionThread = new ConnectionThread(etHandle.getText().toString());
    connectionThread.start();
    }
    });

    btnDisconnect.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
    Thread out = new Thread(new Runnable() {
    @Override
    public void run() {
    try {
    connectionThread.out.writeUTF(DISCONNECT);
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    });
    out.start();
    hideRoomScreen();
    showLoginScreen();
    }
    });

    btnRoom.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
    showRoomScreen();
    Thread out = new Thread(new Runnable() {
    @Override
    public void run() {
    try {
    connectionThread.out.writeUTF(LIST_ROOMS);
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    });
    out.start();
    }
    });

    textMessage.setOnKeyListener(new View.OnKeyListener() {
    @Override
    public boolean onKey(View v, int keyCode, KeyEvent event) {
    if ((keyCode == KeyEvent.KEYCODE_ENTER) && (event.getAction() == KeyEvent.ACTION_DOWN)) {
    final String text = textMessage.getText().toString();
    Thread out = new Thread(new Runnable() {
    @Override
    public void run() {
    try {
    connectionThread.out.writeUTF(SEND_MESSAGE);
    connectionThread.out.writeUTF(text);
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    });
    out.start();
    textMessage.getText().clear();
    return true;
    }
    return false;
    }
    });

    lvRooms.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
    final String roomName = roomsAdapter.getItem(i);
    Thread out = new Thread(new Runnable() {
    @Override
    public void run() {
    try {
    connectionThread.out.writeUTF(JOIN_ROOM);
    connectionThread.out.writeUTF(roomName);
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    });
    out.start();
    hideRoomScreen();
    showChatScreen();
    }
    });
    }

    public void addMessage(String message) {
    adapter.add(message);
    lvMessages.setSelection(adapter.getCount() - 1);
    }

    public void addRoom(final String roomName){
    runOnUiThread(new Runnable() {
    @Override
    public void run() {
    roomsAdapter.add(roomName);
    }
    });
    }

    protected class ConnectionThread extends Thread {
    Socket connection;
    DataInputStream in;
    DataOutputStream out;
    String handle;
    boolean connected;

    public ConnectionThread(String name) {
    handle = name;
    }

    @Override
    public void run() {
    try {
    connection = new Socket("10.0.0.10", 1234);
    connected = true;

    in = new DataInputStream(connection.getInputStream());
    out = new DataOutputStream(connection.getOutputStream());

    out.writeUTF(handle);

    hideLoginScreen();
    btnRoom.callOnClick();

    String command = "";
    while (connected) {
    command = in.readUTF();
    switch (command) {
    case SEND_MESSAGE:
    final String user = in.readUTF();
    final String message = in.readUTF();
    runOnUiThread(new Runnable() {
    @Override
    public void run() {
    addMessage(user + ": " + message);
    }
    });
    break;
    case DISCONNECT:
    showLoginScreen();
    connected = false;
    break;
    case LIST_ROOMS:
    int count = in.readInt();
    runOnUiThread(new Runnable() {
    @Override
    public void run() {
    roomsAdapter.clear();
    }
    });
    for(int i = 0; i < count; i++){
    String roomName = in.readUTF();
    addRoom(roomName);
    }
    break;
    }
    }

    } catch (IOException e) {
    e.printStackTrace();
    }

    }
    }

    private void showLoginScreen() {
    runOnUiThread(new Runnable() {
    @Override
    public void run() {
    loginPanel.setVisibility(View.VISIBLE);
    }
    });
    }

    private void hideLoginScreen() {
    runOnUiThread(new Runnable() {
    @Override
    public void run() {
    loginPanel.setVisibility(View.GONE);
    }
    });
    }

    private void showChatScreen() {
    runOnUiThread(new Runnable() {
    @Override
    public void run() {
    chatPanel.setVisibility(View.VISIBLE);
    }
    });
    }

    private void hideChatScreen() {
    runOnUiThread(new Runnable() {
    @Override
    public void run() {
    chatPanel.setVisibility(View.GONE);
    }
    });
    }

    private void showRoomScreen() {
    runOnUiThread(new Runnable() {
    @Override
    public void run() {
    roomPanel.setVisibility(View.VISIBLE);
    }
    });
    }

    private void hideRoomScreen() {
    runOnUiThread(new Runnable() {
    @Override
    public void run() {
    roomPanel.setVisibility(View.GONE);
    }
    });
    }


    }










    share|improve this question

























      0












      0








      0







      I'm practicing multi-client networking using a Java Server and Android clients. I have done this with Java clients before so I adapted my solution mostly around what I know in Java using multithreading. Which is extending a thread for each client connection created. I usually have a separate ClientConnection class in Java but here I used a protected inner class.



      This solution works but someone mentioned to me that I might want to do this with AsyncTask rather. What benefits would using AsyncTask offer rather than extending a thread the way I have done here?



      Please note I am not asking for any code or how I would go about doing it. Just what benefits it would offer over this method.



      Client Layout



      <RelativeLayout
      xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:tools="http://schemas.android.com/tools"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:paddingLeft="@dimen/activity_horizontal_margin"
      android:paddingRight="@dimen/activity_horizontal_margin"
      android:paddingTop="@dimen/activity_vertical_margin"
      android:paddingBottom="@dimen/activity_vertical_margin"
      tools:context="za.ac.nmu.wrap302.jan2015.MainActivity">

      <LinearLayout
      android:orientation="vertical"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:id="@+id/loginPanel"
      android:layout_alignParentBottom="true">
      <EditText
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:id="@+id/etHandle"
      android:layout_alignParentTop="true"
      android:layout_alignParentLeft="true"
      android:layout_alignParentStart="true"
      android:layout_alignParentRight="true"
      android:layout_alignParentEnd="true"/>
      <Button
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:text="Connect"
      android:id="@+id/btnConnect"
      android:layout_below="@+id/etHandle"
      android:layout_alignParentLeft="true"
      android:layout_alignParentStart="true"
      android:layout_alignRight="@+id/etHandle"
      android:layout_alignEnd="@+id/etHandle"/>
      </LinearLayout>
      <LinearLayout
      android:orientation="vertical"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:id="@+id/chatPanel"
      android:visibility="gone">
      <ListView
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:id="@+id/lvMessages"
      android:layout_below="@+id/btnConnect"
      android:layout_alignParentLeft="true"
      android:layout_alignParentStart="true"
      android:layout_above="@+id/txtMessage"/>
      <Button
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:text="Change Room"
      android:id="@+id/btnRoom"/>
      <EditText
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:id="@+id/txtMessage"
      android:layout_above="@+id/btnDisconnect"
      android:layout_alignParentLeft="true"
      android:layout_alignParentStart="true"
      android:layout_alignRight="@+id/btnDisconnect"
      android:layout_alignEnd="@+id/btnDisconnect"/>
      </LinearLayout>
      <LinearLayout
      android:background="?android:colorBackground"
      android:orientation="vertical"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:id="@+id/roomPanel"
      android:visibility="gone">
      <Button
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:text="Disconnect"
      android:id="@+id/btnDisconnect"
      android:layout_alignParentBottom="true"
      android:layout_alignParentLeft="true"
      android:layout_alignParentStart="true"
      android:layout_alignRight="@+id/lvMessages"
      android:layout_alignEnd="@+id/lvMessages"/>
      <ListView
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:id="@+id/lvRooms"/>
      </LinearLayout>




      Client Code



      public class MainActivity extends AppCompatActivity {
      EditText etHandle;
      ConnectionThread connectionThread;
      private ArrayList<String> messages;
      private ArrayAdapter<String> adapter;

      private ArrayList<String> rooms;
      private ArrayAdapter<String> roomsAdapter;

      private static final String SET_HANDLE = "#SetHandle";
      private static final String SEND_MESSAGE = "#SendMessage";
      private static final String DISCONNECT = "#Disconnect";
      private static final String JOIN_ROOM = "#JoinRoom";
      private static final String LIST_ROOMS = "#ListRooms";

      ListView lvMessages;
      ListView lvRooms;

      EditText textMessage;
      Button btnConnect;
      Button btnDisconnect;
      Button btnRoom;
      LinearLayout chatPanel, roomPanel, loginPanel;

      @Override
      protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);

      etHandle = (EditText) findViewById(R.id.etHandle);
      lvMessages = (ListView) findViewById(R.id.lvMessages);
      textMessage = (EditText) findViewById(R.id.txtMessage);
      btnConnect = (Button) findViewById(R.id.btnConnect);
      btnDisconnect = (Button) findViewById(R.id.btnDisconnect);
      chatPanel = (LinearLayout) findViewById(R.id.chatPanel);
      roomPanel = (LinearLayout) findViewById(R.id.roomPanel);
      loginPanel = (LinearLayout) findViewById(R.id.loginPanel);
      lvRooms = (ListView) findViewById(R.id.lvRooms);
      btnRoom = (Button) findViewById(R.id.btnRoom);

      messages = new ArrayList<String>();
      adapter = new ArrayAdapter<String>(this,
      android.R.layout.simple_selectable_list_item, messages);
      lvMessages.setAdapter(adapter);

      rooms = new ArrayList<String>();
      roomsAdapter = new ArrayAdapter<String>(this,
      android.R.layout.simple_selectable_list_item, rooms);
      lvRooms.setAdapter(roomsAdapter);

      btnConnect.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View view) {
      connectionThread = new ConnectionThread(etHandle.getText().toString());
      connectionThread.start();
      }
      });

      btnDisconnect.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View view) {
      Thread out = new Thread(new Runnable() {
      @Override
      public void run() {
      try {
      connectionThread.out.writeUTF(DISCONNECT);
      } catch (IOException e) {
      e.printStackTrace();
      }
      }
      });
      out.start();
      hideRoomScreen();
      showLoginScreen();
      }
      });

      btnRoom.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View view) {
      showRoomScreen();
      Thread out = new Thread(new Runnable() {
      @Override
      public void run() {
      try {
      connectionThread.out.writeUTF(LIST_ROOMS);
      } catch (IOException e) {
      e.printStackTrace();
      }
      }
      });
      out.start();
      }
      });

      textMessage.setOnKeyListener(new View.OnKeyListener() {
      @Override
      public boolean onKey(View v, int keyCode, KeyEvent event) {
      if ((keyCode == KeyEvent.KEYCODE_ENTER) && (event.getAction() == KeyEvent.ACTION_DOWN)) {
      final String text = textMessage.getText().toString();
      Thread out = new Thread(new Runnable() {
      @Override
      public void run() {
      try {
      connectionThread.out.writeUTF(SEND_MESSAGE);
      connectionThread.out.writeUTF(text);
      } catch (IOException e) {
      e.printStackTrace();
      }
      }
      });
      out.start();
      textMessage.getText().clear();
      return true;
      }
      return false;
      }
      });

      lvRooms.setOnItemClickListener(new AdapterView.OnItemClickListener() {
      @Override
      public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
      final String roomName = roomsAdapter.getItem(i);
      Thread out = new Thread(new Runnable() {
      @Override
      public void run() {
      try {
      connectionThread.out.writeUTF(JOIN_ROOM);
      connectionThread.out.writeUTF(roomName);
      } catch (IOException e) {
      e.printStackTrace();
      }
      }
      });
      out.start();
      hideRoomScreen();
      showChatScreen();
      }
      });
      }

      public void addMessage(String message) {
      adapter.add(message);
      lvMessages.setSelection(adapter.getCount() - 1);
      }

      public void addRoom(final String roomName){
      runOnUiThread(new Runnable() {
      @Override
      public void run() {
      roomsAdapter.add(roomName);
      }
      });
      }

      protected class ConnectionThread extends Thread {
      Socket connection;
      DataInputStream in;
      DataOutputStream out;
      String handle;
      boolean connected;

      public ConnectionThread(String name) {
      handle = name;
      }

      @Override
      public void run() {
      try {
      connection = new Socket("10.0.0.10", 1234);
      connected = true;

      in = new DataInputStream(connection.getInputStream());
      out = new DataOutputStream(connection.getOutputStream());

      out.writeUTF(handle);

      hideLoginScreen();
      btnRoom.callOnClick();

      String command = "";
      while (connected) {
      command = in.readUTF();
      switch (command) {
      case SEND_MESSAGE:
      final String user = in.readUTF();
      final String message = in.readUTF();
      runOnUiThread(new Runnable() {
      @Override
      public void run() {
      addMessage(user + ": " + message);
      }
      });
      break;
      case DISCONNECT:
      showLoginScreen();
      connected = false;
      break;
      case LIST_ROOMS:
      int count = in.readInt();
      runOnUiThread(new Runnable() {
      @Override
      public void run() {
      roomsAdapter.clear();
      }
      });
      for(int i = 0; i < count; i++){
      String roomName = in.readUTF();
      addRoom(roomName);
      }
      break;
      }
      }

      } catch (IOException e) {
      e.printStackTrace();
      }

      }
      }

      private void showLoginScreen() {
      runOnUiThread(new Runnable() {
      @Override
      public void run() {
      loginPanel.setVisibility(View.VISIBLE);
      }
      });
      }

      private void hideLoginScreen() {
      runOnUiThread(new Runnable() {
      @Override
      public void run() {
      loginPanel.setVisibility(View.GONE);
      }
      });
      }

      private void showChatScreen() {
      runOnUiThread(new Runnable() {
      @Override
      public void run() {
      chatPanel.setVisibility(View.VISIBLE);
      }
      });
      }

      private void hideChatScreen() {
      runOnUiThread(new Runnable() {
      @Override
      public void run() {
      chatPanel.setVisibility(View.GONE);
      }
      });
      }

      private void showRoomScreen() {
      runOnUiThread(new Runnable() {
      @Override
      public void run() {
      roomPanel.setVisibility(View.VISIBLE);
      }
      });
      }

      private void hideRoomScreen() {
      runOnUiThread(new Runnable() {
      @Override
      public void run() {
      roomPanel.setVisibility(View.GONE);
      }
      });
      }


      }










      share|improve this question













      I'm practicing multi-client networking using a Java Server and Android clients. I have done this with Java clients before so I adapted my solution mostly around what I know in Java using multithreading. Which is extending a thread for each client connection created. I usually have a separate ClientConnection class in Java but here I used a protected inner class.



      This solution works but someone mentioned to me that I might want to do this with AsyncTask rather. What benefits would using AsyncTask offer rather than extending a thread the way I have done here?



      Please note I am not asking for any code or how I would go about doing it. Just what benefits it would offer over this method.



      Client Layout



      <RelativeLayout
      xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:tools="http://schemas.android.com/tools"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:paddingLeft="@dimen/activity_horizontal_margin"
      android:paddingRight="@dimen/activity_horizontal_margin"
      android:paddingTop="@dimen/activity_vertical_margin"
      android:paddingBottom="@dimen/activity_vertical_margin"
      tools:context="za.ac.nmu.wrap302.jan2015.MainActivity">

      <LinearLayout
      android:orientation="vertical"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:id="@+id/loginPanel"
      android:layout_alignParentBottom="true">
      <EditText
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:id="@+id/etHandle"
      android:layout_alignParentTop="true"
      android:layout_alignParentLeft="true"
      android:layout_alignParentStart="true"
      android:layout_alignParentRight="true"
      android:layout_alignParentEnd="true"/>
      <Button
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:text="Connect"
      android:id="@+id/btnConnect"
      android:layout_below="@+id/etHandle"
      android:layout_alignParentLeft="true"
      android:layout_alignParentStart="true"
      android:layout_alignRight="@+id/etHandle"
      android:layout_alignEnd="@+id/etHandle"/>
      </LinearLayout>
      <LinearLayout
      android:orientation="vertical"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:id="@+id/chatPanel"
      android:visibility="gone">
      <ListView
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:id="@+id/lvMessages"
      android:layout_below="@+id/btnConnect"
      android:layout_alignParentLeft="true"
      android:layout_alignParentStart="true"
      android:layout_above="@+id/txtMessage"/>
      <Button
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:text="Change Room"
      android:id="@+id/btnRoom"/>
      <EditText
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:id="@+id/txtMessage"
      android:layout_above="@+id/btnDisconnect"
      android:layout_alignParentLeft="true"
      android:layout_alignParentStart="true"
      android:layout_alignRight="@+id/btnDisconnect"
      android:layout_alignEnd="@+id/btnDisconnect"/>
      </LinearLayout>
      <LinearLayout
      android:background="?android:colorBackground"
      android:orientation="vertical"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:id="@+id/roomPanel"
      android:visibility="gone">
      <Button
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:text="Disconnect"
      android:id="@+id/btnDisconnect"
      android:layout_alignParentBottom="true"
      android:layout_alignParentLeft="true"
      android:layout_alignParentStart="true"
      android:layout_alignRight="@+id/lvMessages"
      android:layout_alignEnd="@+id/lvMessages"/>
      <ListView
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:id="@+id/lvRooms"/>
      </LinearLayout>




      Client Code



      public class MainActivity extends AppCompatActivity {
      EditText etHandle;
      ConnectionThread connectionThread;
      private ArrayList<String> messages;
      private ArrayAdapter<String> adapter;

      private ArrayList<String> rooms;
      private ArrayAdapter<String> roomsAdapter;

      private static final String SET_HANDLE = "#SetHandle";
      private static final String SEND_MESSAGE = "#SendMessage";
      private static final String DISCONNECT = "#Disconnect";
      private static final String JOIN_ROOM = "#JoinRoom";
      private static final String LIST_ROOMS = "#ListRooms";

      ListView lvMessages;
      ListView lvRooms;

      EditText textMessage;
      Button btnConnect;
      Button btnDisconnect;
      Button btnRoom;
      LinearLayout chatPanel, roomPanel, loginPanel;

      @Override
      protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);

      etHandle = (EditText) findViewById(R.id.etHandle);
      lvMessages = (ListView) findViewById(R.id.lvMessages);
      textMessage = (EditText) findViewById(R.id.txtMessage);
      btnConnect = (Button) findViewById(R.id.btnConnect);
      btnDisconnect = (Button) findViewById(R.id.btnDisconnect);
      chatPanel = (LinearLayout) findViewById(R.id.chatPanel);
      roomPanel = (LinearLayout) findViewById(R.id.roomPanel);
      loginPanel = (LinearLayout) findViewById(R.id.loginPanel);
      lvRooms = (ListView) findViewById(R.id.lvRooms);
      btnRoom = (Button) findViewById(R.id.btnRoom);

      messages = new ArrayList<String>();
      adapter = new ArrayAdapter<String>(this,
      android.R.layout.simple_selectable_list_item, messages);
      lvMessages.setAdapter(adapter);

      rooms = new ArrayList<String>();
      roomsAdapter = new ArrayAdapter<String>(this,
      android.R.layout.simple_selectable_list_item, rooms);
      lvRooms.setAdapter(roomsAdapter);

      btnConnect.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View view) {
      connectionThread = new ConnectionThread(etHandle.getText().toString());
      connectionThread.start();
      }
      });

      btnDisconnect.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View view) {
      Thread out = new Thread(new Runnable() {
      @Override
      public void run() {
      try {
      connectionThread.out.writeUTF(DISCONNECT);
      } catch (IOException e) {
      e.printStackTrace();
      }
      }
      });
      out.start();
      hideRoomScreen();
      showLoginScreen();
      }
      });

      btnRoom.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View view) {
      showRoomScreen();
      Thread out = new Thread(new Runnable() {
      @Override
      public void run() {
      try {
      connectionThread.out.writeUTF(LIST_ROOMS);
      } catch (IOException e) {
      e.printStackTrace();
      }
      }
      });
      out.start();
      }
      });

      textMessage.setOnKeyListener(new View.OnKeyListener() {
      @Override
      public boolean onKey(View v, int keyCode, KeyEvent event) {
      if ((keyCode == KeyEvent.KEYCODE_ENTER) && (event.getAction() == KeyEvent.ACTION_DOWN)) {
      final String text = textMessage.getText().toString();
      Thread out = new Thread(new Runnable() {
      @Override
      public void run() {
      try {
      connectionThread.out.writeUTF(SEND_MESSAGE);
      connectionThread.out.writeUTF(text);
      } catch (IOException e) {
      e.printStackTrace();
      }
      }
      });
      out.start();
      textMessage.getText().clear();
      return true;
      }
      return false;
      }
      });

      lvRooms.setOnItemClickListener(new AdapterView.OnItemClickListener() {
      @Override
      public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
      final String roomName = roomsAdapter.getItem(i);
      Thread out = new Thread(new Runnable() {
      @Override
      public void run() {
      try {
      connectionThread.out.writeUTF(JOIN_ROOM);
      connectionThread.out.writeUTF(roomName);
      } catch (IOException e) {
      e.printStackTrace();
      }
      }
      });
      out.start();
      hideRoomScreen();
      showChatScreen();
      }
      });
      }

      public void addMessage(String message) {
      adapter.add(message);
      lvMessages.setSelection(adapter.getCount() - 1);
      }

      public void addRoom(final String roomName){
      runOnUiThread(new Runnable() {
      @Override
      public void run() {
      roomsAdapter.add(roomName);
      }
      });
      }

      protected class ConnectionThread extends Thread {
      Socket connection;
      DataInputStream in;
      DataOutputStream out;
      String handle;
      boolean connected;

      public ConnectionThread(String name) {
      handle = name;
      }

      @Override
      public void run() {
      try {
      connection = new Socket("10.0.0.10", 1234);
      connected = true;

      in = new DataInputStream(connection.getInputStream());
      out = new DataOutputStream(connection.getOutputStream());

      out.writeUTF(handle);

      hideLoginScreen();
      btnRoom.callOnClick();

      String command = "";
      while (connected) {
      command = in.readUTF();
      switch (command) {
      case SEND_MESSAGE:
      final String user = in.readUTF();
      final String message = in.readUTF();
      runOnUiThread(new Runnable() {
      @Override
      public void run() {
      addMessage(user + ": " + message);
      }
      });
      break;
      case DISCONNECT:
      showLoginScreen();
      connected = false;
      break;
      case LIST_ROOMS:
      int count = in.readInt();
      runOnUiThread(new Runnable() {
      @Override
      public void run() {
      roomsAdapter.clear();
      }
      });
      for(int i = 0; i < count; i++){
      String roomName = in.readUTF();
      addRoom(roomName);
      }
      break;
      }
      }

      } catch (IOException e) {
      e.printStackTrace();
      }

      }
      }

      private void showLoginScreen() {
      runOnUiThread(new Runnable() {
      @Override
      public void run() {
      loginPanel.setVisibility(View.VISIBLE);
      }
      });
      }

      private void hideLoginScreen() {
      runOnUiThread(new Runnable() {
      @Override
      public void run() {
      loginPanel.setVisibility(View.GONE);
      }
      });
      }

      private void showChatScreen() {
      runOnUiThread(new Runnable() {
      @Override
      public void run() {
      chatPanel.setVisibility(View.VISIBLE);
      }
      });
      }

      private void hideChatScreen() {
      runOnUiThread(new Runnable() {
      @Override
      public void run() {
      chatPanel.setVisibility(View.GONE);
      }
      });
      }

      private void showRoomScreen() {
      runOnUiThread(new Runnable() {
      @Override
      public void run() {
      roomPanel.setVisibility(View.VISIBLE);
      }
      });
      }

      private void hideRoomScreen() {
      runOnUiThread(new Runnable() {
      @Override
      public void run() {
      roomPanel.setVisibility(View.GONE);
      }
      });
      }


      }







      java android multithreading networking






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 13 '18 at 1:56









      Sithe

      1509




      1509
























          1 Answer
          1






          active

          oldest

          votes


















          1














          AsyncTask was not designed to remain active and to receive commands, so I'm not agree with who suggest to use it.
          You need a Thread that remains active for an undetermined amount of time and that receive commands. It's physically possible to use AsyncTask in that similar way but this case is similar to one that uses a Component for a complete different thing, like when using a TextView to display images (by substitute common ImageView and manually draw on TextView): it's possible but....the question is: "WHY?"



          There isn't any advantage by using it.






          share|improve this answer





















            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53272673%2fis-using-asynctask-in-a-multi-user-chat-android-client-better-than-extending-a-c%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            1














            AsyncTask was not designed to remain active and to receive commands, so I'm not agree with who suggest to use it.
            You need a Thread that remains active for an undetermined amount of time and that receive commands. It's physically possible to use AsyncTask in that similar way but this case is similar to one that uses a Component for a complete different thing, like when using a TextView to display images (by substitute common ImageView and manually draw on TextView): it's possible but....the question is: "WHY?"



            There isn't any advantage by using it.






            share|improve this answer


























              1














              AsyncTask was not designed to remain active and to receive commands, so I'm not agree with who suggest to use it.
              You need a Thread that remains active for an undetermined amount of time and that receive commands. It's physically possible to use AsyncTask in that similar way but this case is similar to one that uses a Component for a complete different thing, like when using a TextView to display images (by substitute common ImageView and manually draw on TextView): it's possible but....the question is: "WHY?"



              There isn't any advantage by using it.






              share|improve this answer
























                1












                1








                1






                AsyncTask was not designed to remain active and to receive commands, so I'm not agree with who suggest to use it.
                You need a Thread that remains active for an undetermined amount of time and that receive commands. It's physically possible to use AsyncTask in that similar way but this case is similar to one that uses a Component for a complete different thing, like when using a TextView to display images (by substitute common ImageView and manually draw on TextView): it's possible but....the question is: "WHY?"



                There isn't any advantage by using it.






                share|improve this answer












                AsyncTask was not designed to remain active and to receive commands, so I'm not agree with who suggest to use it.
                You need a Thread that remains active for an undetermined amount of time and that receive commands. It's physically possible to use AsyncTask in that similar way but this case is similar to one that uses a Component for a complete different thing, like when using a TextView to display images (by substitute common ImageView and manually draw on TextView): it's possible but....the question is: "WHY?"



                There isn't any advantage by using it.







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Nov 13 '18 at 7:15









                emandt

                876156




                876156






























                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.





                    Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                    Please pay close attention to the following guidance:


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53272673%2fis-using-asynctask-in-a-multi-user-chat-android-client-better-than-extending-a-c%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    Bressuire

                    Vorschmack

                    Quarantine