使用ViewPager和选项卡时出现“Java.lang.IllegalStateException Activity has been destroyed”错误。

112
我有一个应用程序,使用ActionBarSherlock的选项卡模式。我有5个选项卡,每个选项卡的内容都使用片段处理。但是对于第二个选项卡,我有一个包含ViewPager元素的xml文件,其中又有一些片段页面。当我最初启动应用程序时,我可以轻松地在选项卡之间切换,但当我第二次点击选项卡2时,就会出现上述错误。主要活动如下:
public class MainActivity extends SherlockFragmentActivity
{
    @Override
    protected void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ActionBar actionBar = getSupportActionBar();

        ActionBar.Tab tab1 = actionBar.newTab().setText("Tab1");
        ActionBar.Tab tab3 = actionBar.newTab().setText("Tab3");
        ActionBar.Tab tab2 = actionBar.newTab().setText("Tab2");
        ActionBar.Tab tab4 = actionBar.newTab().setText("Tab4");
        ActionBar.Tab tab5 = actionBar.newTab().setText("Tab5");

        Fragment fragment1 = new Tab1();
        Fragment fragment3 = new Tab3();
        Fragment fragment2 = new Tab2();
        Fragment fragment5 = new Tab5();
        Fragment fragment4 = new Tab4();

        tab1.setTabListener(new MyTabListener(fragment1));
        tab3.setTabListener(new MyTabListener(fragment3));
        tab2.setTabListener(new MyTabListener(fragment2));
        tab5.setTabListener(new MyTabListener(fragment5));
        tab4.setTabListener(new MyTabListener(fragment4));

        actionBar.addTab(tab1);
        actionBar.addTab(tab2);
        actionBar.addTab(tab3);
        actionBar.addTab(tab4);
        actionBar.addTab(tab5); 

        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
    }

    class MyTabListener implements ActionBar.TabListener
    {
        Fragment fragment;

        public MyTabListener(Fragment fragment)
        {
            this.fragment = fragment;
        }

        @Override
        public void onTabSelected(com.actionbarsherlock.app.ActionBar.Tab tab,FragmentTransaction ft) 
        {
            ft.replace(R.id.fragment_container,fragment);
        }

        @Override
        public void onTabUnselected(com.actionbarsherlock.app.ActionBar.Tab tab,FragmentTransaction ft) 
        {

        }

        @Override
        public void onTabReselected(com.actionbarsherlock.app.ActionBar.Tab tab,FragmentTransaction ft) 
        {

        }
    }
}

没有ViewPager的片段类如下所示:

public class Tab1 extends Fragment 
{
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState)
    {
        return inflater.inflate(R.layout.activity_tab1, container, false);
    }
}

ViewPager中的片段类如下:
public class Tab2 extends Fragment 
{
    ViewPager mViewPager;
    private MyFragmentPagerAdapter mMyFragmentPagerAdapter;  
    private static int NUMBER_OF_PAGES = 5;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState)
    {
        View view =  inflater.inflate(R.layout.activity_tab2, container, false); 
        return view;
    }

    @Override
    public void onViewCreated(View view,Bundle savedInstanceState)
    {
        super.onViewCreated(view, savedInstanceState);
        mViewPager = (ViewPager) view.findViewById(R.id.viewpager);
        mMyFragmentPagerAdapter = new MyFragmentPagerAdapter(getChildFragmentManager());  
        mViewPager.setAdapter(mMyFragmentPagerAdapter);  
    }

    private static class MyFragmentPagerAdapter extends FragmentPagerAdapter 
    {    
        public MyFragmentPagerAdapter(FragmentManager fm) 
        {  
             super(fm);  
        }  

        @Override  
        public Fragment getItem(int index) 
        {  
             return PageFragment.newInstance("My Message " + index);
        }  

        @Override  
        public int getCount() 
        {  
             return NUMBER_OF_PAGES;  
        }  
   }
}

根据我在不同地方阅读到的内容(如有错误,请纠正),这是因为片段管理器在第二次尝试重用来自已不存在的活动的片段,从而导致错误。但我不确定为什么会在这里发生,因为我没有使用片段活动。根据 logcat 的记录,错误出现在 Tab2 类的 onViewCreated 方法中,在 mViewPager.setAdapter(mMyFragmentPagerAdapter) 一行。非常感谢您的帮助...谢谢。
03-04 12:01:05.468: E/AndroidRuntime(2474): FATAL EXCEPTION: main
03-04 12:01:05.468: E/AndroidRuntime(2474): java.lang.IllegalStateException: Activity has been destroyed
03-04 12:01:05.468: E/AndroidRuntime(2474):     at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1342)
03-04 12:01:05.468: E/AndroidRuntime(2474):     at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:595)
03-04 12:01:05.468: E/AndroidRuntime(2474):     at android.support.v4.app.BackStackRecord.commitAllowingStateLoss(BackStackRecord.java:578)
03-04 12:01:05.468: E/AndroidRuntime(2474):     at android.support.v4.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:139)
03-04 12:01:05.468: E/AndroidRuntime(2474):     at android.support.v4.view.ViewPager.populate(ViewPager.java:1011)
03-04 12:01:05.468: E/AndroidRuntime(2474):     at android.support.v4.view.ViewPager.populate(ViewPager.java:880)
03-04 12:01:05.468: E/AndroidRuntime(2474):     at android.support.v4.view.ViewPager.setAdapter(ViewPager.java:433)
03-04 12:01:05.468: E/AndroidRuntime(2474):     at com.example.tabs.Tab2.onViewCreated(Tab2.java:31)
03-04 12:01:05.468: E/AndroidRuntime(2474):     at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:925)
03-04 12:01:05.468: E/AndroidRuntime(2474):     at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1088)
03-04 12:01:05.468: E/AndroidRuntime(2474):     at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:682)
03-04 12:01:05.468: E/AndroidRuntime(2474):     at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1444)
03-04 12:01:05.468: E/AndroidRuntime(2474):     at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:429)
03-04 12:01:05.468: E/AndroidRuntime(2474):     at android.os.Handler.handleCallback(Handler.java:587)
03-04 12:01:05.468: E/AndroidRuntime(2474):     at android.os.Handler.dispatchMessage(Handler.java:92)
03-04 12:01:05.468: E/AndroidRuntime(2474):     at android.os.Looper.loop(Looper.java:123)
03-04 12:01:05.468: E/AndroidRuntime(2474):     at android.app.ActivityThread.main(ActivityThread.java:3687)
03-04 12:01:05.468: E/AndroidRuntime(2474):     at java.lang.reflect.Method.invokeNative(Native Method)
03-04 12:01:05.468: E/AndroidRuntime(2474):     at java.lang.reflect.Method.invoke(Method.java:507)
03-04 12:01:05.468: E/AndroidRuntime(2474):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:842)
03-04 12:01:05.468: E/AndroidRuntime(2474):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
03-04 12:01:05.468: E/AndroidRuntime(2474):     at dalvik.system.NativeStart.main(Native Method)

所以我认为我可能已经找到了问题所在。当通过Eclipse调试器查看变量mMyFragmentPagerAdapter(类Tab2)时,我发现它有一个FragmentManager变量,当第一次单击Tab2时,它有一个名为mActivity的字段,该字段指向MainActivity。但是在从tab2切换到其他选项卡并再次查看mActivity时,它的值为null,这或许可以解释为什么会出现“Activity已被销毁”的错误。 - Yulric Sequeira
14个回答

0
我发现我在后台运行了一个计时器。当活动被杀死时,计时器仍在运行。在计时器完成回调中,我访问片段对象以执行一些工作,这就是错误所在!!!片段存在,但活动不存在。
如果您有计时器或任何后台线程的服务,请确保不要访问片段对象。

这对我来说更像是一条评论,而不是一个答案。无论如何,请注意语法、标点、大写、拼写等方面的重要性。请编辑以解决这些问题。您可以在StackOverflow.com/help的SO帮助中心找到更多信息。 - SherylHohman

0

最新的androidx版本已经修复了这个bug。而且著名的解决方法现在会导致崩溃,所以我们现在不需要它了。


0

我之前也遇到过这个问题,在这里没有找到解决方案,所以我想分享我的解决方法,以防其他人再次遇到这个问题。

我之前的代码是:

public void finishAction() {
  onDestroy();
  finish();
}

并通过删除"onDestroy();"这一行来解决了问题。
public void finishAction() {
  finish();
}

我编写初始代码的原因是: 我知道当您执行“finish()”时,活动将调用“onDestroy()”,但我正在使用线程,并且希望确保在启动下一个活动之前销毁所有线程,并且看起来“finish()”并不总是立即完成。 我需要处理/减少大量“位图”并显示大型“位图”,我正在努力改善我的应用程序中的内存使用。
现在,我将使用不同的方法杀死线程,并从“onDestroy()”中执行此方法,在我认为需要终止所有线程时。
public void finishAction() {
  onDestroyThreads();
  finish();
}

0

这个问题让我在Xamarin上感到非常困扰。

我在一个Fragment中实现了ViewPager和TabLayout,而这个Fragment本身又被实现在DrawerLayout中,遇到了这个问题:

 - DrawerLayout
   - DrawerFragment
     - TabLayout
     - TabViewPager
       - TabViewPagerFragments

所以你必须在你的DrawerFragment中实现以下代码。 请注意选择正确的FragmentManager路径。因为你可能有两个不同的FragmentManager引用:

  1. Android.Support.V4.App.FragmentManager
  2. Android.App.FragmentManager

--> 选择你使用的那个。 如果你想要使用ChildFragmentManager,你必须在ViewPager中使用类声明Android.App.FragmentManager

Android.Support.V4.App.FragmentManager

请在您的“Main”片段中实现以下方法 - 例如:DrawerFragment
public override void OnDetach() {
    base.OnDetach();
    try {
        Fragment x = this;
        var classRefProp = typeof(Fragment).GetProperty("class_ref", BindingFlags.NonPublic | BindingFlags.Static);
        IntPtr classRef = (IntPtr)classRefProp.GetValue(x);
        var field = JNIEnv.GetFieldID(classRef, "mChildFragmentManager", "Landroid/support/v4/app/FragmentManagerImpl;");
        JNIEnv.SetField(base.Handle, field, IntPtr.Zero);
    }
    catch (Exception e) {
        Log.Debug("Error", e+"");
    }
}

Android.App.FragmentManager

public class TabViewPager: Android.Support.V13.App.FragmentPagerAdapter {}

这意味着您必须使用Android.App.FragmentManager来初始化ViewPager。

在您的“主”Fragment中实现以下方法 - 在此示例中为:DrawerFragment

public override void OnDetach() {
    base.OnDetach();
    try {
        Fragment x = this;
        var classRefProp = typeof(Fragment).GetProperty("class_ref", BindingFlags.NonPublic | BindingFlags.Static);
        IntPtr classRef = (IntPtr)classRefProp.GetValue(x);
        var field = JNIEnv.GetFieldID(classRef, "mChildFragmentManager", "Landroid/app/FragmentManagerImpl;");
        JNIEnv.SetField(base.Handle, field, IntPtr.Zero);
    }
    catch (Exception e) {
        Log.Debug("Error", e+"");
    }
}

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