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”时。不。您永远不应该依赖具有高度可控生命周期的 Activity。您的 Activity 应该以这样一种方式设计,即无论何时销毁和重新创建它,它都能正常工作。

要跨轮换等保留信息,请添加代码onSaveInstanceBundle,然后检查它onCreate并提取保存的值。

于 2013-03-26T21:22:02.520 回答
0

这是标准的 Android 行为。看看这段 Android文档

除非您另外指定,否则配置更改(例如屏幕方向、语言、输入设备等的更改)将导致您当前的活动被破坏,并通过 onPause()、onStop() 和onDestroy() 视情况而定。如果活动在前台或对用户可见,则在该实例中调用 onDestroy() 后,将创建活动的新实例,其中包含前一个实例从 onSaveInstanceState(Bundle) 生成的任何已保存实例状态。

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

于 2013-03-27T03:08:10.120 回答
0

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

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

我弄清楚发生了什么。我使用用于启动 A 的相同 Intent 对象也启动 B。在方向更改和 B 完成后,Android 系统检测到 Activity A 需要重建,因为 A 是在方向不同时最后构建的。系统将使用最初用于构建 A 的相同 Intent 对象重构 A。但是,Intent 对象被修改为启动 B,因此系统将重构 Activity B 而不是 Activity 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. 设备处于纵向模式。用户启动 Activity A。系统将构造带有 Intent I 的 Activity A,其目标设置为 A。
  2. 活动 A 通过将目标更改为 B 来修改其 Intent I。
  3. Activity A 以 Intent I 开始一个 Activity。系统将构造 Activity B,因为 I 现在指向 B。
  4. B 现在正在运行。用户将设备方向更改为横向。
  5. 用户单击单击侦听器调用 myFinishingClickHandler 的按钮。该方法在 Activity B 上调用 finish()。
  6. 活动 B 结束。系统开始恢复活动 A 的过程。
  7. 系统注意到 Activity A 是在设备处于纵向时构建的,但现在设备处于横向模式。系统将尝试重新创建活动 A。现有的 Activity A 通过其销毁流程(调用 onDestroy)发送。
  8. 系统将使用保存的 Intent I 重构 Activity A。但是,I 的目标仍然是 Activity B。系统改为构建 Activity B 而不是 Activity A。

解决方案:不要共享 Intents 来启动活动。使用 Intent 复制构造函数。

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

于 2017-05-02T04:44:02.180 回答