私はAndroid用の単純なアプリケーションを開発しており、アプリケーションに必要なFTPコールとXML解析にasynctaskを使用するように切り替えようとしました(これは天気アプリのFYIです)。アンドロイドのasynctaskの潜在的なバグ
残念ながら、私はアプリで非常に奇妙な動作に気付き始めました。私はデバッグし、doInBackground()メソッド内のコードが順不同で実行されていることを私の恐怖に発見しました!
簡潔にするために、以下のコードは簡略化されています(ただし、catchステートメントはロールバックされます)。 asynctaskはonResume()で呼び出され、次にftpサーバーを呼び出し、ファイルをダウンロードして解析します。何が起こっているのですか(私はあなたが以下に見ることができるデバッグステートメントを通して非常にはっきりと見ることができます)、ファイルのダウンロードが完了する前に解析呼び出しが行われています。だから、デバッグ文の観点から、順序がしばしばある:
- GETファイル
- 前に解析ファイルの前
- エラーと解析ファイルの後に(ファイルがまだダウンロードしていないと!)
- ファイルを取得した後
私はもっと多くのコード(必要な場合はすべて!)を提供してくれることを嬉しく思います。
@Override
public void onResume()
{
if(!inOnResume)
{
inOnResume = true;
super.onResume();
File file = new File(getFilesDir(), selectedCity);
new GetBOMWeatherData().execute(file);
}
}
private class GetBOMWeatherData extends AsyncTask<File, Void, Void>
{
boolean fileDownloaded = false;
@Override
protected void onPreExecute()
{
showDialog(PROGRESS_KEY);
super.onPreExecute();
}
@Override
protected Void doInBackground(File... params)
{
FileOutputStream fos = null;
try
{
fos = new FileOutputStream(params[0]);
}
catch (FileNotFoundException e)
{
Log.e("ApiException", "There was an error opening the file output stream.", e);
cancel(false);
}
try
{
Log.d("Before get file", "Before get file");
DataRetriever.getPageContent(selectedCity, fos);
Log.d("After get file", "After get file");
fileDownloaded = true;
}
catch (ApiException e)
{
Log.d("After get file with error", "After get file with error");
Log.e("ApiException", "There was an error opening the file output stream.", e);
cancel(false);
}
finally
{
Log.d("After get file finally", "After get file finally");
}
try
{
Log.d("Before parse file", "Before parse file");
forecasts = parseXML(selectedCity);
Log.d("After parse file", "After parse file");
lastDownloaded.put(selectedCity, new Date());
}
catch (FactoryConfigurationError e)
{
Log.d("After parse file with error", "After parse file with error");
Log.e("XMLParsingException", "There was an error in the factory configuration.", e);
cancel(false);
}
finally
{
Log.d("After parse file finally", "After parse file finally");
}
return null;
}
@Override
protected void onPostExecute(Void file)
{
inOnResume = false;
super.onPostExecute(file);
dismissDialog(PROGRESS_KEY);
updateView();
}
@Override
protected void onCancelled()
{
super.onCancelled();
showDialog(FAILURE_KEY);
}
}
編集:奇妙なエラーが発生し始めたことが、順不同で実行されていたという理由が判明しました。メインのUIスレッドですべてを実行すると、それは動作しますが、asynctaskにすべて入れるとすぐにXML解析エラーが発生します。この問題は、アプリケーションが解析しようとしたときにファイルが完全にダウンロードされていないことが原因です。
'私はデバッグステートメントで非常にはっきりとわかります。順序が変更される可能性があります。ログがプッシュされる遅延はさまざまです...実際にアプリケーションをデバッグしようとしましたか? – WarrenFaith
はい、私はそれを実行すると、順番に実行されているように見えます(ログ・ステートメントでさえもデバッグしています)。私はおそらく、私がコードラインを一歩進んだりするのにかかる時間の増加をデバッグすると、すべてが順番に起こることを意味するのではないかと思う。 – chesterm8
エミュレータでアプリケーションをデバッグしていますか?場合によっては、エミュレータはonResumeメソッドを複数回実行するように見えることがあります。新しいスレッドを開始する前に、スレッドが実行中であるかどうかを確認するためにロックを行ってください。 – Janusz