AsyncTask を実行して Web から情報をダウンロードし、その情報をアクティビティのローカル変数に入れるボタンがあります。この情報は、別のボタンを押すことで表示できます。また、UI のビューを更新して、同期が実行中か準備完了かを示します。
何らかの理由で、onPostExecute が UI とローカル変数を期待どおりに更新しないことがありますが、更新されることもあります。デバッガーで確認したところ、変数 (handleDownloadComplete) を更新するコードが実行されていますが、UI とデータ表示ボタンが正しく更新されません。注: 問題は主に接続がタイムアウトしたときに発生しますが、デバッガーで戻り値が正しいことを確認しました - 「接続がタイムアウトしました」、それでもアクティビティは更新されません。
ありがとう!
AsyncTask クラス:
public class DownloadDataTask extends AsyncTask<String, Integer, String> {
public interface DownloadCompleteHandler
{
void handleDownloadComplete(String result);
}
private DownloadCompleteHandler handler;
@Override
protected String doInBackground(String... urls) {
try {
return downloadUrl(urls[0]);
} catch (IOException e) {
return "Unable to retrieve web page. URL may be invalid.";
}
}
@Override
protected void onPostExecute(String result) {
handler.handleDownloadComplete(result);
}
private String downloadUrl(String urlStr) throws IOException
{
InputStream is = null;
String result = new String();
try {
URL url = new URL(urlStr);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(10000);
conn.setConnectTimeout(15000);
conn.setRequestMethod("GET");
conn.setDoInput(true);
conn.connect();
int response = conn.getResponseCode();
is = conn.getInputStream();
BufferedReader in = new BufferedReader(new InputStreamReader(is));
String inputLine;
while ((inputLine = in.readLine()) != null) {
result += inputLine;
}
}
catch (MalformedURLException ex) {
result = "Malformed URL: " + urlStr;
}
catch (SocketTimeoutException ex) {
result = "Connection timed out";
}
finally {
if (is != null)
is.close();
}
return result;
}
public void setHandler(DownloadCompleteHandler handler) {
this.handler = handler;
}
}
アクティビティ:
public class MainActivity extends Activity implements DownloadDataTask.DownloadCompleteHandler{
private String downloadResult = "";
private Boolean isSyncing = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public void onResume() {
super.onResume();
checkNetworkConnection();
}
@Override
protected void onSaveInstanceState(Bundle savedInstanceState) {
savedInstanceState.putString(KEY_DOWNLOAD_RESULT, downloadResult);
savedInstanceState.putBoolean(KEY_IS_SYNCING, isSyncing);
super.onSaveInstanceState(savedInstanceState);
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
downloadResult = savedInstanceState.getString(KEY_DOWNLOAD_RESULT);
isSyncing = savedInstanceState.getBoolean(KEY_IS_SYNCING);
updateAppDataView();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_settings:
settingsMenu();
return true;
case R.id.action_show_result:
showUrlResultDialog();
return true;
case R.id.action_sync:
getHttpData();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
void settingsMenu() {
Intent intent = new Intent(this, SettingsActivity.class);
startActivity(intent);
}
private void checkNetworkConnection() {
ConnectivityManager connMgr = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isConnected()) {
// test app connection
} else {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage(R.string.titleNoNetwork).setMessage(R.string.msgNoNetwork);
builder.setCancelable(false);
builder.setNegativeButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
});
AlertDialog dialog = builder.create();
dialog.show();
}
}
private void getHttpData()
{
if (isSyncing) return;
isSyncing = true;
TextView view = (TextView)findViewById(R.id.textWebResult);
view.setText("Syncing");
String serverId = PreferenceManager.getDefaultSharedPreferences(this).getString(getString(R.string.keyServerIp), "");
String url = "https://" + serverId;
DownloadDataTask downloader = new DownloadDataTask();
downloader.setHandler(this);
downloader.execute(url);
}
public void handleDownloadComplete(String result)
{
downloadResult = result;
TextView view = (TextView)findViewById(R.id.textWebResult);
view.setText("Ready");
isSyncing = false;
}
private void showUrlResultDialog()
{
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage(R.string.titleUrlResultData).setMessage(downloadResult);
builder.setNeutralButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
AlertDialog dialog = builder.create();
dialog.show();
}
}
編集:実装が欠落onSaveInstanceState
していることに気付きonRestoreInstanceState
、接続がタイムアウトしたときにのみ問題が発生し、何らかの理由でアクティビティが再開される可能性があるため、それが原因である可能性があると考えました。だから私はそれらを(上記のコードでも)追加しましたが、問題はまだ発生しています...
アイデアはありますか?