Прочитав несколько сообщений и прочитав на странице разработчиков об ASYNCTASK, я придумал следующий код и назначил его кнопке:
private class TalkToServerTask extends AsyncTask<String, Void, String> {
@Override
protected String doInBackground(String... params) {
String response = "";
try {
InetAddress serverAddr = InetAddress.getByName(params[0]);
Socket s = new Socket(serverAddr, Integer.valueOf(params[1]));
PrintWriter out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(s.getOutputStream())), true);
// WHERE YOU ISSUE THE COMMANDS
out.println(params[2]);
// BufferedReader input = new BufferedReader(
// new InputStreamReader(s.getInputStream()));
DataInputStream dataInputStream = null;
dataInputStream = new DataInputStream(s.getInputStream());
st = dataInputStream.readLine().toString();
// String st = s.readLine();
// st = input.readLine();
// read line(s)
s.close();
return st;
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return response;
}
@Override
protected void onPostExecute(String result) {
serverresponse = result;
}
}
Идея заключается в том, что при нажатии кнопки ASyncTask отправляет слово "getDomains" в консольное приложение, запущенное на моем сервере, сервер действует на него и отправляет обратно строку со списком доменов, созданных на сервере электронной почты.
Я проверил, что сервер получает команду "getdomains", и он, в свою очередь, отвечает на строку с ограничениями по каналам. Однако проблема заключается в том, что я установил Toast для вывода результатов транзакции сокета, и тост ничего не показывает. Если я снова нажму кнопку, тост отобразит список доменов. Для меня кажется, что сокет сначала возвращает пустой
Вот код кнопки:
case R.id.btnDomains:
SharedPreferences sp = PreferenceManager
.getDefaultSharedPreferences(this);
IpAddress = sp.getString("ipaddress", "0.0.0.0");
Serverport = sp.getString("tcpport", "12345");
buttonpressed = "domains";
// TalkToServerTask task = new TalkToServerTask();
new TalkToServerTask().execute(IpAddress, Serverport, "getDomains");
Intent buttonActivity = new Intent(MainActivity.this, Rules.class);
buttonActivity.putExtra(MainActivity.DOMAINLIST, serverresponse);
Toast.makeText(getApplicationContext(), serverresponse,
Toast.LENGTH_SHORT).show();
переменная "serverresponse" - это то, что сначала показывает пустой, но затем показывает список серверов.
Как отметил Топош, AsyncTask работает над отдельным потоком.
Поэтому поток выполняется и еще не получил результата, когда вы в первый раз нажимаете кнопку.
Вы должны показать данные в методе onPostExecute. Также вы должны передать контекст вашему AsyncTask.
public TalkToServerTask(Context context) {
this.context = context;
}
@Override
protected void onPostExecute(String result) {
Intent buttonActivity = new Intent(context, Rules.class);
buttonActivity.putExtra(MainActivity.DOMAINLIST, result);
Toast.makeText(context.getApplicationContext(), result, Toast.LENGTH_SHORT).show();
}
Вам просто нужно немного изменить свой код,
Вам нужно переместить эти 3 строки,
Intent buttonActivity = new Intent(MainActivity.this, Rules.class);
buttonActivity.putExtra(MainActivity.DOMAINLIST, serverresponse);
// and also the line to startActivity() as well.
Toast.makeText(getApplicationContext(), serverresponse,
Toast.LENGTH_SHORT).show();
от вашего Switch..case
к onPostExecute
из AsyncTask
где вы написали serverresponse = result
Это потому, что AsyncTask работает в другом потоке, а вы выполнили в Swtich... случай не так, что следующая строка кода не будет выполняться до завершения AsyncTask, поэтому весь зависимый код должен быть записан в onPostExecute задачи,
AsynTask
запускается в отдельном потоке из потока пользовательского интерфейса. Таким образом, есть 2 потока, выполняющихся параллельно. Пока вы пытаетесь отобразить список в тосте в основном потоке пользовательского интерфейса, AsynTask
все еще готовится к извлечению списка или, возможно, созданию сокетов в своем потоке. Следовательно, данные списка все еще пусты.
postexecute
метод Asynctask
запускается в основном потоке пользовательского интерфейса, поэтому его безопасно и правильно обновлять пользовательский интерфейс.
AsyncTask
должен работать не сразу, он должен работать в отдельном потоке. вы должны изменить пользовательский интерфейс сonPostExecute