AndroidスタジオでAsyncTaskを使用して、バックグラウンドでTCP接続を使用しています。次に、PreExecute
のランナーが5秒のタイムアウトでランナーを実行し、cancel(true)
をAsyncTask
に呼び出します(DataOutputStream
にはタイムアウトのオーバーライドがないため)。AsyncTaskは、最初の試行でOnCancel()を呼び出さない
問題は、まずアプリケーションを開いてテストし、ログインしようとすると「サーバーに接続しています」だけです。 "TCP Timeout"というメッセージは決して呼び出されません。もう一度ログインしようとすると、正常に動作します。しかし、初めてではありません。だから私はcancel(true)
が決して呼び出されないと思います。私はPreExecute
でタイムアウトランナーを実行しようとしましたが、onLoginButtonClicked
コードの後ろに(これは愚かなことですが)何も動作しません。
私は間違っていますか?
private class AsynchronisedTask extends AsyncTask<String, Void, String> {
@Override
protected String doInBackground(String... strings) {
String serverAnswer = "";
if (!isCancelled())
serverAnswer = new TCP().SendToServer(strings[0]);
return serverAnswer;
}
@Override
protected void onPostExecute(String result) {
if (result.contains("Accepted")) {
Toast.makeText(LoginActivity.this, "Logged in.", Toast.LENGTH_SHORT).show();
Intent intent = new Intent(LoginActivity.this, ProfilePageActivity.class);
Profile profile = new Profile();
profile.setProfileName(usernameText.getText().toString());
intent.putExtra("Username", usernameText.getText().toString());
startActivity(intent);
} else {
Toast.makeText(LoginActivity.this, "Invalid username or password.", Toast.LENGTH_SHORT).show();
}
}
@Override
protected void onPreExecute() {
handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
if (asynchronisedTask.getStatus() == AsyncTask.Status.RUNNING) {
asynchronisedTask.cancel(true);
}
}
}, 5000);
Toast.makeText(LoginActivity.this, "Contacting server.", Toast.LENGTH_SHORT).show();
}
@Override
protected void onCancelled(String result) {
Toast.makeText(LoginActivity.this, "TCP Timeout.", Toast.LENGTH_SHORT).show();
}
}
public class TCP implements ITCP {
private String IP = "192.168.1.33"; // LOCAL "192.168.1.33" PUBLIC **.***.***.***
private int PORT = 9000;
@Override
public String SendToServer(String stringToServer) {
String answer = "";
Socket socket = null;
DataOutputStream dataOutputStream = null;
DataInputStream dataInputStream = null;
try {
socket = new Socket(IP, PORT);
dataOutputStream = new DataOutputStream(socket.getOutputStream());
dataInputStream = new DataInputStream(socket.getInputStream());
dataOutputStream.writeUTF(stringToServer);
answer = dataInputStream.readUTF();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (dataOutputStream != null) {
try {
dataOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (dataInputStream != null) {
try {
dataInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
if (answer instanceof String)
return answer;
else return answer.toString();
}
どのようにOnCancelledがdoInBackgroundの後に呼び出されるのは、別のスレッドが5秒のタイムアウトをしてからスレッドでcancel(true)を呼び出すときですか? そして、私はすでにdoInBackgroundのisCanceled()をチェックしていたと思いますか? – Bobfromfinance
これは、doInBackgroundの後までは、ドキュメントのことであるため、呼び出されません:) onCanceledは、キャンセルされたタスクの場合は基本的にonPostExecuteの代わりに呼び出され、同じ目的(UIクリーンアップ)を目的としています。 isCanceledのチェックは値が変わることがあります。 doInBackgroundは並列スレッドで実行されることを忘れないでください。だから、isCanceledは最初は誤っているかもしれませんが、1ミリ秒後に真になります。だからこそ冒頭の虚偽はそれが後でキャンセルされないことを意味するわけではありません。 –