在重合方向更改后重新创建完成的活动

时间:2013-03-26 21:10:52

标签: android orientation restart oncreate activity-finish

我不知道这种行为是否正常,因为我认为调用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()来处理它。但是,它看起来很丑陋,因为完成的活动应该永远消失,现在我必须明确处理它。 :( 我是否对活动生命周期或保留片段有任何误解?

3 个答案:

答案 0 :(得分:2)

如果你在Android上工作,每当你听到自己说“此活动将仅在X之后关闭”。别。您永远不应该依赖具有高度受控生命周期的Activity。你的Activity应该以这样的方式设计,无论它何时被销毁和重新创建,它都能正常工作。

要保留旋转等信息,请将代码添加到onSaveInstanceBundle,然后在onCreate上检查并提取已保存的值。

答案 1 :(得分:0)

这是标准的Android行为。看一下Android documentation的这一段。

  

除非您另行指定,否则配置更改(例如屏幕方向,语言,输入设备等的更改)将导致您的当前活动被破坏,通过onPause(),onStop的正常活动生命周期过程( )和onDestroy()视情况而定。如果活动位于前台或对用户可见,则在该实例中调用onDestroy()后,将创建活动的新实例,其中包含先前实例生成的任何savedInstanceState的onSaveInstanceState(束)。

为避免这种情况,您可以在其清单中设置android:configChanges属性。对于任何类型的配置更改,您说您在那里处理,您将收到对当前活动的onConfigurationChanged(配置)方法的调用,而不是重新启动。但是,如果配置更改涉及您未处理的任何内容,则仍将重新启动活动,并且不会调用onConfigurationChanged(Configuration)。

答案 2 :(得分:0)

我遇到了同样的问题。也就是说,我有一个活动A,它将使用startActivityForResult启动活动B. B的方向被清单锁定。 A的方向未锁定。

当我旋转设备以使方向不同时,将不会重新创建活动B.这是预期和正常的。但是,一旦我执行完成()活动B的UI动作,而不是看到活动A被重建并显示在屏幕上,我再次显示了活动B.此外,正在调用Activity的B onActivityResult,而不是A的onActivityResult。

我弄清楚发生了什么。我使用了用于启动A的相同Intent对象来启动B.在方向更改之后和B完成之后,Android系统检测到需要重建活动A,因为A是在方向不同时最后构建的。系统将使用最初用于构建A的相同Intent对象重建A.但是,Intent对象被修改为启动B,因此系统将重建活动B而不是活动A.

我的代码遵循类似于下面的逻辑:

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.系统将使用Intent I构建活动A,其目标设置为A.
  2. 活动A通过将目标更改为B来修改其意图I.
  3. 活动A使用Intent I启动活动。系统将构建活动B,因为我现在指向B。
  4. B现在正在运行。用户将设备方向更改为横向。
  5. 用户点击其点击侦听器调用myFinishingClickHandler的按钮。该方法在Activity B上调用finish()。
  6. 活动B结束。系统开始恢复活动A的过程。
  7. 系统注意到当设备处于纵向方向时构建了活动A,但现在设备处于横向模式。系统将尝试重新创建活动A.现有的活动A通过其销毁流程(调用onDestroy)发送。
  8. 系统将使用保存的Intent I重建活动A.但是,我的目标仍然是活动B.系统改为构建活动B而不是活动A.
  9. 解决方案:不要分享用于启动活动的意图。使用Intent复制构造函数。

    另外,锁定您的活动'方向更少担心方向变化(其他配置变化将导致您的活动被重建,例如更改语言)。