我有一个按钮,它运行 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
实现,并认为这可能是原因,因为问题仅在连接超时时发生,这可能导致活动因某种原因重新启动。所以我添加了它们(也在上面的代码中),但问题仍然存在......
有什么想法吗?