私はAndroidでAsyncTasksを使用していて、問題に取り組んでいます。
簡単な例として、1つのAsyncTaskを持つアクティビティを取り上げます。バックグラウンドでのタスクは見事なことは何もしません。8秒間スリープするだけです。
onPostExecute()メソッドのAsyncTaskの最後で、ボタンの表示ステータスをView.VISIBLEに設定しているだけで、結果を確認するだけです。
これで、AsyncTaskの動作中に(8秒のスリープウィンドウ内で)ユーザーが電話の向きを変更することを決定するまで、これはうまく機能します。
Androidアクティビティのライフサイクルを理解しており、アクティビティが破棄されて再作成されることを知っています。
ここで問題が発生します。AsyncTaskはボタンを参照しており、最初にAsyncTaskを開始したコンテキストへの参照を保持しているようです。
この古いコンテキスト(ユーザーが向きを変更したため)がnullになり、AsyncTaskが表示しようとしているボタンへの参照用にNPEをスローすることを期待します。
代わりに、NPEはスローされず、AsyncTaskはボタン参照がnullではないと見なし、表示に設定します。結果?画面には何も起きていません!
更新:WeakReference
アクティビティを維持し、構成の変更が発生したときに切り替えることで、これに取り組んでいます。これは面倒です。
コードは次のとおりです。
public class Main extends Activity {
private Button mButton = null;
private Button mTestButton = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mButton = (Button) findViewById(R.id.btnStart);
mButton.setOnClickListener(new OnClickListener () {
@Override
public void onClick(View v) {
new taskDoSomething().execute(0l);
}
});
mTestButton = (Button) findViewById(R.id.btnTest);
}
private class TaskDoSomething extends AsyncTask<Long, Integer, Integer>
{
@Override
protected Integer doInBackground(Long... params) {
Log.i("LOGGER", "Starting...");
try {
Thread.sleep(8000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 0;
}
@Override
protected void onPostExecute(Integer result) {
Log.i("LOGGER", "...Done");
mTestButton.setVisibility(View.VISIBLE);
}
}
}
それを実行してみて、AsyncTaskが機能している間に電話の向きを変更してください。