在阅读了几篇文章并阅读关于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以弹出套接字事务的结果,并且toast没有显示任何内容。如果我再次点击按钮,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”首先显示为空,但随后显示服务器列表。
答案 0 :(得分:3)
正如Thepoosh所提到的,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();
}
答案 1 :(得分:0)
您只需要稍微更改一下代码,
你需要移动这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
的{{1}}到AsyncTask
{/ 1}
那是因为AsyncTask在不同的线程中运行,而你在Swtich中执行...情况并不是说下一行代码不会被执行,直到AsyncTask结束,所以所有依赖代码都应该写在onPostExecute中任务。
答案 2 :(得分:0)
AsynTask
在与UI线程不同的线程上运行。所以有2个线程并行运行。当您尝试在主UI线程的吐司中显示列表时,AsynTask
仍在准备获取列表,或者可能在其自己的线程中创建套接字。因此列表数据仍然是空的。
postexecute
的{{1}}方法在主UI线程上运行,因此更新其中的UI是安全和正确的。