111

タブ モードで ActionBarSherlock を使用するアプリケーションがあります。5 つのタブがあり、各タブのコンテンツはフラグメントを使用して処理されます。ただし、tab2 の場合、いくつかのフラグメント ページを持つ ViewPager 要素を保持する xml ファイルのフラグメントがあります。アプリケーションを最初に起動すると、問題なくタブを切り替えることができますが、tab2 を 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;  
        }  
   }
}

私が別の場所で読んだことから (間違っている場合は修正してください)、これは、2 番目のパスのフラグメント マネージャーが、存在しないアクティビティのフラグメントを再利用しようとするために発生し、エラーが発生します。しかし、フラグメント アクティビティを使用していないため、ここでこれが発生する理由はわかりません。logcat によると、エラーは Tab2 クラス、mViewPager.setAdapter(mMyFragmentPagerAdapter) という行の onViewCreated メソッドにあります。どんな助けでも大歓迎です...ありがとう。

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)
4

14 に答える 14

284

これは、新しく追加されたネストされたフラグメントのサポートのバグのようです。基本的に、子FragmentManagerはアクティビティから切り離されると、内部状態が壊れてしまいます。私のためにそれを修正した短期的な回避策は、あなたが呼び出すonDetach()すべてのものに以下を追加することです:FragmentgetChildFragmentManager()

@Override
public void onDetach() {
    super.onDetach();

    try {
        Field childFragmentManager = Fragment.class.getDeclaredField("mChildFragmentManager");
        childFragmentManager.setAccessible(true);
        childFragmentManager.set(this, null);

    } catch (NoSuchFieldException e) {
        throw new RuntimeException(e);
    } catch (IllegalAccessException e) {
        throw new RuntimeException(e);
    }
}
于 2013-03-27T10:18:14.767 に答える
13

私はまったく同じ問題を抱えています。私が見つけた唯一の回避策は、タブが変更されるたびにフラグメントを新しいインスタンスに置き換えることです。

ft.replace(R.id.fragment_container, Fragment.instantiate(PlayerMainActivity.this, fragment.getClass().getName()));

本当の解決策ではありませんが、以前のフラグメント インスタンスを再利用する方法が見つかりませんでした...

于 2013-03-19T23:53:46.827 に答える
2

LocalBroadcastManager を使用していたため、このエラーが発生しました。

unregisterReceiver(intentReloadFragmentReceiver);

それ以外の:

LocalBroadcastManager.getInstance(this).unregisterReceiver(intentReloadFragmentReceiver);
于 2014-01-10T14:47:38.080 に答える
2

私は同じ問題に遭遇し、後でFragmentActivity の呼び出しsuper.onCreate( savedInstanceState );に失敗したことがわかりました。onCreate()

于 2014-12-19T06:41:53.423 に答える
1

フラグメントが完全に初期化される前に子にアクセスしようとすると、まったく同じエラーが発生しましたFragmentManager(つまり、アクティビティにアタッチされるか、少なくともonCreateView()呼び出されます)。それ以外の場合、アクティビティFragmentManagerで初期化され、前述の例外が発生します。null

于 2014-05-13T06:03:05.713 に答える
0

私はこの問題を抱えていて、ここで解決策を見つけることができなかったので、他の誰かがこの問題を再び抱えている場合に備えて、私の解決策を共有したいと思います.

私はこのコードを持っていました:

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

「onDestroy();」の行を削除して問題を解決しました。

public void finishAction() {
  finish();
}

最初のコードを書いた理由: 「finish()」を実行するとアクティビティが「onDestroy()」を呼び出すことはわかっていますが、私はスレッドを使用しており、次のアクティビティを開始する前にすべてのスレッドが確実に破棄されるようにしたかったのです。 、そして「finish()」は必ずしも即時ではないようです。大量の「ビットマップ」を処理/削減し、大きな「ビットマップ」を表示する必要があり、アプリでのメモリ使用の改善に取り組んでいます

ここで、別のメソッドを使用してスレッドを強制終了し、このメソッドを "onDestroy();" から実行します。そして、すべてのスレッドを強制終了する必要があると思うとき。

public void finishAction() {
  onDestroyThreads();
  finish();
}
于 2014-04-03T08:48:33.633 に答える