java.lang.IllegalStateException: Activity has been destroyed 意思是:Java运行时出现了非法状态异常,因为活动已经被销毁。

3

我正在使用 Robolectric 进行开发,对于 Android 开发还很陌生。我已经创建了一个使用 Activity 的测试类,并且测试通过。现在我想要为 Fragment 创建一个测试。

@RunWith(RobolectricTestRunner.class)
public class LoginFragmentTest {
    private LoginFragment fragment;

    @Before
    public void setup() {
        fragment = new LoginFragment();
        startFragment(fragment);
        assertThat(fragment, notNullValue());
        assertThat(fragment.getActivity(), notNullValue());
    }

    private void startFragment(LoginFragment fragment) {
        FragmentManager fragmentManager = new FragmentActivity().getSupportFragmentManager();
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction.add(fragment, null);
        fragmentTransaction.commit();
    }

    @Test
    public void login() {
        EditText idEditText = (EditText)fragment.getActivity().findViewById(R.id.main_id);
        assertThat(idEditText, notNullValue());
    }
}

这是我为Fragment类编写的第一个测试类。它会抛出异常。
"java.lang.IllegalStateException: Activity has been destroyed" in startFragment#fragmentTransaction.commit().

有人知道如何修复这个问题吗?你可以在https://github.com/msbaek/frame-test找到完整的代码。提前感谢!

嗯,提交片段事务之前不要销毁您的活动? - njzk2
4个回答

4
在我的情况下,问题出现在创建活动时。我正在使用:
 activity = Robolectric.buildActivity(MyActivity.class).get();

它应该是这样的

 activity = Robolectric.buildActivity(MyActivity.class).create().get();

希望它能帮助到有需要的人 :D

3
@RunWith(RobolectricTestRunner.class)
public class LoginFragmentTest {
    private LoginFragment fragment;

    @Before
    public void setup() {
        fragment = new LoginFragment();
        startFragment();
        assertThat(fragment, notNullValue());
        assertThat(fragment.getActivity(), notNullValue());
    }

    private void startFragment() {
        FragmentActivity activity = new FragmentActivity();
        shadowOf(activity).callOnCreate(null);
        shadowOf(activity).callOnStart();
        shadowOf(activity).callOnResume();

        FragmentManager fragmentManager = activity.getSupportFragmentManager();
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction.add(fragment, null);
        fragmentTransaction.commit();
    }

    @Test
    public void login() {
        EditText idEditText = (EditText) fragment.getView().findViewById(R.id.main_id);
        assertThat(idEditText, notNullValue());
    }
}

这是一个可用的版本。以下3行非常重要(来自Robolectric源代码中的DialogFragmentTest)。

        shadowOf(activity).callOnCreate(null);
        shadowOf(activity).callOnStart();
        shadowOf(activity).callOnResume();

1

这些片段应该从一个Activity中显示。流程应该是:

  • 在FragmentActivity类中分配一个新的fragment对象
  • 获取fragment manager来添加新分配的fragment

在您的情况下,您没有与真实activity的连接。您使用new FragmentActivity()分配了一个FragmentActivity并尝试获取支持管理器。虽然它可以编译,但没有“真正”的activity能够管理您的fragment。片段可以添加到已经显示的活动中,但在这种情况下不是这样。

我建议阅读这个页面,因为它非常好地解释了这些内容: http://developer.android.com/guide/components/fragments.html


谢谢!我成功地将活动连接到片段。 - Myeonseok Baek
在 Robolectric 的上下文中,“真实”(real)活动是什么意思? - MaciejGórski
@백명석,你是如何将Fragment连接到Activity的?我也遇到了类似的问题。 - muneikh

1
当我在子片段中使用fragmentTransaction.commitAllowingStateLoss()时发生了这种情况,其父片段已设置setRetainInstance(true)。我将activity作为属性,导致在旋转时泄漏了activity。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接