0

この質問は、AsyncTaskを殺す必要がある に関係していますProgressDialog。タスクの実行中、アクティビティは破棄され、再作成されます (電話の回転など)。の助けを借りて新しいダイアログが作成されますがonSaveInstanceState()AsyncTask以前に破棄されたアクティビティによって生成された はそれを見ることができません。

もしよろしければ、絵を描いてください...(例のための簡単なモックアップコード)。

public class Bob extends Activity {

    private ProgressDialog m_d;

    public void onCreate(Bundle b) {
        m_d = new ProgressDialog(this);
        // ...
        if (b != null) {
            if (b.getBoolean("dialog") == true)
                m_d.show();
        }
        // ...
    }

    public void onSaveInstanceState(Bundle b) {
        super.onSaveInstanceState(b);
        b.putBoolean("dialog", (m_d.isShowing()));
    }

    public void onDestroy() {
        if (m_d.isShowing()) {
            m_d.dismiss();
            m_d = null;
        }
        //...
    }
}

AsyncTask onPreExecute()し、m_d.show()onPostExecute()ませんm_d.hide()

問題は、アクティビティが再作成されたとき (電話のローテーションなど)、AsyncTask古いm_d. それはnull、で殺されたからonDestroy()です。

m_dアクティビティが再作成されたときに作成された新しい はありません。だから今、私はProgressDialogそれを殺すはずだった男がそれをonPostExecute()見ることができない.

それで?古いAsyncTaskものから新しいProgressDialogものに信号を送る必要があります。

private OnItemSelectedListener onSpinnerSelection = new OnItemSelectedListener() {

    public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
        // ...
        new Switcharoo().execute();
    }
}

private class Switcharoo extends AsyncTask<Void, Void, Void> {

    protected void onPreExecute() {
        m_d.show();
        // ...
    }

    protected void onPostExecute() {
        if (m_d != null) m_d.hide();
        // ...
    }

    protected Void doInBackground(Void... arg0) {
        // ...
    }
}

タスクの実行中に Android がアクティビティを強制終了しなければ問題ありません。期待どおりにProgressDialogポップアップして消えます。

タスクの実行中に何らかの理由で Android がアクティビティを再起動することを決定した場合、m_dで再作成してもnull、新しいものではなく古いものがあります。onPostExecute()onCreate()m_d

4

1 に答える 1

1

2つの問題があります。1つは、AsyncTaskを作成したアクティビティにバインドされていることです。つまり、アクティビティのインスタンスです。

アクティビティローテーション間で存続させたい場合は、別の場所に保存する必要があります(たとえばこれを確認してください)。いずれの場合も、新しいアクティビティからの参照が必要です(モデルフラグメント、つまり、UIが設定されていないフラグメントを使用することもできますsetRetainInstance(true))。

m_d新しく作成されたアクティビティから非同期タスクへの参照を取得すると、非同期タスクと、新しいダイアログでそれを更新するセッターメソッドをローカルにすることを妨げるものは何もありません。

ガベージコレクションを可能にするために、アクティビティとダイアログ自体を指す弱参照を持つことも良い習慣であることに注意してください。そうしないと、タスク自体の実行が終了するまで、ダイアログ(およびおそらくアクティビティ自体)が解放されません。

于 2013-03-13T22:34:34.100 に答える