1

finish()を呼び出すとアクティビティの再作成が停止すると思われるため、この動作が正常かどうかはわかりません。

アクティビティクラスの抜粋は次のとおりです。

public class MyActivity extends FragmentActivity {

    private RetainFragment retainFragment;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        ......

        retainFragment = getSupportFragmentManager().findFragmentByTag("RetainFragment");
        if(retainFragment == null) {
            retainFragment = new RetainFragment();
            getSupportFragmentManager().beginTransaction().add(retainFragment, "RetainFragment").commitAllowingStateLoss();
        }
        if(retainFragment.isFinish) {
            Log.v("MyActivity", "isFinish == true");
            this.finish();
        }
    }

    // a on-click event handler for a finish button
    public void onFinishClicked(View view) {
         retainFragment.isFinish = true;
         this.finish();
    }

    private class RetainFragment extends Fragment {
        private boolean isFinish = false;

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            this.setRetainInstance(true);
        }
    }

}

アクティビティは永続的であり(他の永続変数もRetainFragmentに保存しますが、表示しませんでした)、ユーザーが終了ボタンをクリックした後にのみ閉じられます。この時点でonFinishClicked(View)が呼び出され、アクティビティが呼び出されます。システムによって終了する必要があります。画面を同時に回転させた後、システムによって再作成されるとは思いません。これはめったに発生しないので、onCreate()メソッド内でfinish()を再度呼び出すことで処理します。ただし、ここでは、終了したアクティビティが永久に停止することになっているため、かなり醜いように見えます。これを明示的に処理する必要があります。:(アクティビティのライフサイクルまたは私の側の保持フラグメントの誤解はありますか?

4

3 に答える 3

2

Androidで作業している場合は、「このアクティビティは後でのみ終了します」と言うのを聞いたときはいつでもX。しないでください。高度に制御されたライフサイクルを持つアクティビティに依存しないでください。アクティビティは、いつ破棄されて再作成されても、正しく機能するように設計する必要があります。

ローテーションなどで情報を保持するには、にコードを追加してからonSaveInstanceBundle、でそれを確認onCreateし、保存された値を引き出します。

于 2013-03-26T21:22:02.520 に答える
0

これはAndroidの標準的な動作です。Androidドキュメントのこの段落をご覧ください。

特に指定しない限り、構成の変更(画面の向き、言語、入力デバイスなどの変更など)により、現在のアクティビティが破棄され、onPause()、onStop()、およびの通常のアクティビティライフサイクルプロセスが実行されます。必要に応じてonDestroy()。アクティビティがフォアグラウンドにあるか、ユーザーに表示されている場合、そのインスタンスでonDestroy()が呼び出されると、前のインスタンスがonSaveInstanceState(Bundle)から生成したsavedInstanceStateを使用して、アクティビティの新しいインスタンスが作成されます。

これを回避するには、マニフェストでandroid:configChanges属性を設定できます。そこで処理すると言うあらゆるタイプの構成変更について、再起動する代わりに、現在のアクティビティのonConfigurationChanged(Configuration)メソッドへの呼び出しを受け取ります。ただし、構成の変更に処理しないものが含まれる場合でも、アクティビティは再開され、onConfigurationChanged(Configuration)は呼び出されません。

于 2013-03-27T03:08:10.120 に答える
0

私はまったく同じ問題に直面していました。つまり、startActivityForResultを使用してアクティビティBを開始するアクティビティAがありました。Bの向きはマニフェストによってロックされています。Aの向きはロックされていません。

向きが異なるようにデバイスを回転させた場合、アクティビティBは再作成されませんでした。これは予想された正常なことです。ただし、アクティビティAが再構築されて画面に表示されるのではなく、アクティビティBを終了するUIアクションを実行すると、アクティビティBが再び表示されました。さらに、アクティビティのBのonActivityResultが、AのonActivityResultの代わりに呼び出されていました。

私は何が起こっているのか理解しました。Aの起動に使用したのと同じIntentオブジェクトを使用してBも起動しました。向きを変更した後、Bが終了した後、Androidシステムは、向きが異なるときにAが最後にビルドされたため、アクティビティAを再ビルドする必要があることを検出します。システムは、最初にAのビルドに使用されたものと同じIntentオブジェクトを使用してAを再構築します。ただし、Intentオブジェクトは代わりにBを起動するように変更されたため、システムはアクティビティAではなくアクティビティBを再構築します。

私のコードは以下のようなロジックに従いました:

public class A extends Activity {
     @Override
     protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //...omitted code for clarity...
        Intent i = getIntent();
        i.setClass(this, B.class);
        startActivityForResult(i, 0);
     }

     @Override
     public void onActivityResult(int requestCode, int resultCode, Intent data) {
         //...omitted code for clarity...
     }
 }

そして私のアクティビティBは次のようになりました:

public class B extends Activity {
     //...omitted code for clarity....

     public void myFinishingClickHandler(View clickedView) {
         //...omitted code for clarity...
         finish();
     }
}

シナリオのクイックウォークスルー:

  1. デバイスはポートレートモードです。ユーザーがアクティビティAを起動します。システムは、ターゲットがAに設定されているインテントIを使用してアクティビティAを構築します。
  2. アクティビティAは、ターゲットをBに変更することにより、インテントIを変更します。
  3. アクティビティAはインテントIでアクティビティを開始します。IがBを指しているため、システムはアクティビティBを作成します。
  4. Bは現在実行中です。ユーザーがデバイスの向きを横向きに変更します。
  5. ユーザーがボタンをクリックし、そのクリックリスナーがmyFinishingClickHandlerを呼び出します。このメソッドは、アクティビティBでfinish()を呼び出します。
  6. アクティビティBが終了します。システムは、アクティビティAを復元するプロセスを開始します。
  7. システムは、デバイスが縦向きのときにアクティビティAが作成されたが、現在はデバイスが横向きモードになっていることを通知します。代わりに、システムはアクティビティAの再作成を試みます。既存のアクティビティAは、その破棄フローを介して送信されます(onDestroyを呼び出します)。
  8. システムは、保存されたインテントIを使用してアクティビティAを再構築します。ただし、ターゲットは引き続きアクティビティBです。システムは、アクティビティAではなくアクティビティBを構築します。

解決策:アクティビティを開始するためのインテントを共有しないでください。インテントコピーコンストラクターを使用します。

また、アクティビティの向きをロックして、向きの変更について心配する必要がなくなります(他の構成の変更により、言語の変更など、アクティビティが再構築されます)。

于 2017-05-02T04:44:02.180 に答える