Is using AsyncTask in a multi-user chat Android client better than extending a connection thread?
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
add a comment |
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
add a comment |
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
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
java android multithreading networking
asked Nov 13 '18 at 1:56
Sithe
1509
1509
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
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.
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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.
add a comment |
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.
add a comment |
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.
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.
answered Nov 13 '18 at 7:15
emandt
876156
876156
add a comment |
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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