Является ли использование AsyncTask в клиенте Android для многопользовательского чата лучше, чем расширение потока соединения? - PullRequest
0 голосов
/ 13 ноября 2018

Я практикую многопользовательскую сеть, используя Java Server и клиенты Android. Я делал это с клиентами Java раньше, поэтому я адаптировал свое решение в основном к тому, что я знаю в Java, используя многопоточность. Который расширяет поток для каждого созданного клиентского соединения. У меня обычно есть отдельный класс ClientConnection в Java, но здесь я использовал защищенный внутренний класс.

Это решение работает, но кто-то сказал мне, что я мог бы сделать это с AsyncTask. Какие преимущества дает использование AsyncTask вместо расширения потока, как я это сделал здесь?

Пожалуйста, обратите внимание, что я не спрашиваю какой-либо код или как я буду делать это. Каковы преимущества этого метода по сравнению с этим методом?

Макет клиента

<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>

Код клиента

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

}

1 Ответ

0 голосов
/ 13 ноября 2018

AsyncTask не был предназначен для того, чтобы оставаться активным и получать команды, поэтому я не согласен с тем, кто предлагает его использовать. Вам нужен поток, который остается активным в течение неопределенного времени и который получает команды. Физически возможно использовать AsyncTask таким же образом, но этот случай похож на тот, который использует Компонент для совершенно другой вещи, например, при использовании TextView для отображения изображений (путем замены общего ImageView и ручного рисования на TextView): это возможно, но .... вопрос: «ПОЧЕМУ?»

Нет пользы от него.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...