2

私はこれに対する解決策を探すのに何時間も費やし、助けが必要です。

AndroidアプリのアクティビティにネストされたAsyncTaskがあり、ユーザーが新しいAsyncTaskを開始せずに、処理中に電話を回転できるようにしたいと思います。onRetainNonConfigurationInstance()とgetLastNonConfigurationInstance()を使用しようとしました。

私は仕事を続けることができます。ただし、ローテーション後、onPostExecute()の結果は外部クラス変数に保存されません。もちろん、ゲッターとセッターを試してみました。onPostExecuteに変数をダンプすると、問題ありません。しかし、onClickリスナーから変数にアクセスしようとすると、nullになります。

たぶん、コードはあなたのために問題を明らかにするでしょう。

public class MainActivity extends BaseActivity {

    private String possibleResults = null;
    private Object task = null;

    @Override
    public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);

            this.task = getLastNonConfigurationInstance();

            setContentView(R.layout.menu);

            if ((savedInstanceState != null)
                            && (savedInstanceState.containsKey("possibleResults"))) {
                    this.possibleResults = savedInstanceState
                                    .getString("possibleResults");
            }

            if (this.possibleResults == null) {
                    if (this.task != null) {
                            if (this.task instanceof PossibleResultWebService) {
                                    ((PossibleResultWebService) this.task).attach();
                            }

                    } else {
                            this.task = new PossibleResultWebService();
                            ((PossibleResultWebService) this.task).execute(this.matchToken);
                    }
            }

            Button button;
            button = (Button) findViewById(R.id.menu_resultButton);
            button.setOnClickListener(resultListener);
    }

    @Override
    protected void onResume() {
            super.onResume();
    }

    OnClickListener resultListener = new OnClickListener() {
            @Override
            public void onClick(View v) {

                    Spinner s = (Spinner) findViewById(R.id.menu_heatSpinner);
                    int heatNo = s.getSelectedItemPosition() + 1;
                    Intent myIntent = new Intent(MainActivity.this,
                                    ResultActivity.class);
                    myIntent.putExtra("matchToken", MainActivity.this.matchToken);
                    myIntent.putExtra("heatNo", String.valueOf(heatNo));
                    myIntent.putExtra("possibleResults",
                                    MainActivity.this.possibleResults);

                    MainActivity.this.startActivityForResult(myIntent, ADD_RESULT);
            }
    };

    private class PossibleResultWebService extends AsyncTask<String, Integer, Integer> {

            private ProgressDialog pd;
            private InputStream is;
            private boolean finished = false;
            private String possibleResults = null;

            public boolean isFinished() {
                    return finished;
            }

            public String getPossibleResults() {
                    return possibleResults;
            }

            @Override
            protected Integer doInBackground(String... params) {
                // quite long code
            }

            public void attach() {
                    if (this.finished == false) {
                            pd = ProgressDialog.show(MainActivity.this, "Please wait...",
                                            "Loading data...", true, false);
                    }
            }

            public void detach() {
                    pd.dismiss();
            }

            @Override
            protected void onPreExecute() {
                    pd = ProgressDialog.show(MainActivity.this, "Please wait...",
                                    "Loading data...", true, false);
            }

            @Override
            protected void onPostExecute(Integer result) {
                    possibleResults = convertStreamToString(is);
                    MainActivity.this.possibleResults = possibleResults;

                    pd.dismiss();
                    this.finished = true;
            }
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {

            super.onSaveInstanceState(outState);

            if (this.possibleResults != null) {
                    outState.putString("possibleResults", this.possibleResults);
            }

    }

    @Override
    public Object onRetainNonConfigurationInstance() {
            if (this.task instanceof PossibleResultWebService) {
                    ((PossibleResultWebService) this.task).detach();
            }
            return (this.task);
    }

}

4

1 に答える 1

0

これは、アクティビティをインスタンス化するたびに(つまり、新しいOuterClass.this参照を取得するたびに)OnClickListenerを作成しているためですが、アクティビティのインスタンス化の間にAsyncTaskを保存し、最初にインスタンス化されたアクティビティへの参照を保持しているためです。 OuterClass.thisを参照してその中で。

これを正しく行う方法の例については、 https://github.com/commonsguy/cw-android/tree/master/Rotation/RotationAsync/を参照してください。

この問題を解決するために、彼のRotationAwareTaskにattach()メソッドとdetach()メソッドがあることがわかります。

AsyncTask内のOuterClass.this参照が、画面の向きの変更の間に(onRetainNonConfigurationInstanceを使用して)保持する場合、常に最初にインスタンス化されたアクティビティを指すことを確認するには、デフォルトのコンストラクターによって毎回インクリメントされる静的カウンターを使用して、作成ごとにカウントに設定されるインスタンスレベルの変数を出力します。

于 2012-04-30T21:29:45.213 に答える