35

非常に不可解なバグが発生しており、作業を開始する方法さえわかりません。

私は 1 つのアクティビティを持つ単純なアプリを持っています。ビューは Fragments で実装されています。フラグメントの 1 つに ViewPager が含まれています。そこで、v4 サポート ライブラリの getChildFragmentManager クラスを使用することにしました。また、ActionBarSherlock を使用する必要がありましたが、v4 ライブラリの v11 には同梱されていないため、問題が発生しました。

ABS の v4 サポート ライブラリを v11 ライブラリに置き換えることでこれを修正し、ViewPager を含め、すべてがコンパイルされて動作しているように見えました。

ここに奇妙な部分があります:

ViewPager を含むフラグメントが初めて開いたとき、正しく動作します。しかし、ナビゲートされた 2 回目にアプリがクラッシュし、役に立たないスタック トレースが生成されます。デバッグの結果、getChildFragmentManager によって返される FragmentManager に問題があることがわかりました。No Activity エラーがスローされます。

何が原因なのか誰にもわかりませんか?

関連すると思われるコードを投稿します。

ありがとう、デビッド

4

8 に答える 8

46

この回避策につながったjeremyvillalobos の回答(非常に役に立ちました)のリンクをたどりました。

public class CustomFragment extends Fragment {
    private static final Field sChildFragmentManagerField;

    static {
        Field f = null;
        try {
            f = Fragment.class.getDeclaredField("mChildFragmentManager");
            f.setAccessible(true);
        } catch (NoSuchFieldException e) {
            Log.e(LOGTAG, "Error getting mChildFragmentManager field", e);
        }
        sChildFragmentManagerField = f;
    }

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

        if (sChildFragmentManagerField != null) {
            try {
                sChildFragmentManagerField.set(this, null);
            } catch (Exception e) {
                Log.e(LOGTAG, "Error setting mChildFragmentManager field", e);
            }
        }
    }

    ...
}

フラグメントを再インスタンス化する必要なく、うまく機能します。

于 2013-09-18T14:45:11.733 に答える
23

これは、で報告されたバグのようです

https://code.google.com/p/android/issues/detail?id=42601

変数

FragmentManagerImpl mChildFragmentManager;

Fragment.java では、デタッチ時に null に設定されません。したがって、次にフラグメントがロードされるとき、変数は引き続き最後の親を指します。

そのスレッドで説明されているように、回避策は Fragment を再インスタンス化することです。

私の場合、ActionBar タブでフラグメントを切り替えていました。問題のある Fragment には Fragments がネストされており、ファイル ローダー Fragment に戻るとアプリがクラッシュしていました。したがって、これは回避策のコードです。

class MainTabsListener implements ActionBar.TabListener {
    public Fragment fragment;
    public int TabPosition;

    public MainTabsListener(Fragment fragment, int tab_position) {
        this.fragment = fragment;
        TabPosition = tab_position;
    }

    @Override
    public void onTabReselected(Tab tab, FragmentTransaction ft) {
    }

    @Override
    public void onTabSelected(Tab tab, FragmentTransaction ft) {
        CurrentFragment = fragment;
        CurrentTabSelectedPos = TabPosition;

        /**
         * This is a work-around for Issue 42601
         * https://code.google.com/p/android/issues/detail?id=42601
         * 
         * The method getChildFragmentManager() does not clear up
         * when the Fragment is detached.
         */
        if( fragment instanceof FileLoaderFragment ){
            fragment = reinstatiateFileLoaderFragment();
        }

        ft.replace(R.id.fragment_container, fragment);

    }

    @Override
    public void onTabUnselected(Tab tab, FragmentTransaction ft) {
        ft.remove(fragment);
    }

}
于 2013-05-17T06:09:30.600 に答える
2

私も同じ問題を抱えてる。

アクティビティでは、transaction.replace(...)でフラグメントを切り替えるための3つのボタンがあります

FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); transaction.replace(R.id.layout_tablet_paneau, mLigneMessageFragment);

このフラグメントの1つには、カスタムFragmentPagerAdapterを含むViewPageが含まれています。したがって、ネストされたフラグメントを許可するには、getChildFragmentManager()を実行する必要があります。

コンストラクターはここにあります:

public LignePagerAdapter(Fragment ligneMessageTabletFragment) {
        super(ligneMessageTabletFragment.getChildFragmentManager());
    }

したがって、同じエラーが発生します。このフラグメントの最初の表示は機能しませんが、他のフラグメントを表示してこのフラグメントに戻ると、次の例外が発生します。

02-26 11:57:50.798:D / ACRA(776):トースト+ワーカーが終了するのを待ちます。アプリケーションを強制終了しますか?true
02-26 11:57:50.798:E / AndroidRuntime(776):致命的な例外:メイン
02-26 11:57:50.798:E / AndroidRuntime(776):java.lang.IllegalStateException:アクティビティなし
02-26 11:57:50.798:E / AndroidRuntime(776):android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1075)
02-26 11:57:50.798:E / AndroidRuntime(776):android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1070)
02-26 11:57:50.798:E / AndroidRuntime(776):android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:1861)
02-26 11:57:50.798:E / AndroidRuntime(776):android.support.v4.app.Fragment.performActivityCreated(Fragment.java:1474)
02-26 11:57:50.798:E / AndroidRuntime(776):android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:931)
02-26 11:57:50.798:E / AndroidRuntime(776):android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1088)
02-26 11:57:50.798:E / AndroidRuntime(776):android.support.v4.app.BackStackRecord.run(BackStackRecord.java:682)
02-26 11:57:50.798:E / AndroidRuntime(776):android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1444)
02-26 11:57:50.798:E / AndroidRuntime(776):android.support.v4.app.FragmentManagerImpl $ 1.run(FragmentManager.java:429)
02-26 11:57:50.798:E / AndroidRuntime(776):android.os.Handler.handleCallback(Handler.java:587)で
02-26 11:57:50.798:E / AndroidRuntime(776):android.os.Handler.dispatchMessage(Handler.java:92)
02-26 11:57:50.798:E / AndroidRuntime(776):android.os.Looper.loop(Looper.java:132)
02-26 11:57:50.798:E / AndroidRuntime(776):android.app.ActivityThread.main(ActivityThread.java:4126)
02-26 11:57:50.798:E / AndroidRuntime(776):java.lang.reflect.Method.invokeNative(ネイティブメソッド)
02-26 11:57:50.798:E / AndroidRuntime(776):java.lang.reflect.Method.invoke(Method.java:491)で
02-26 11:57:50.798:E / AndroidRuntime(776):com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:844)
02-26 11:57:50.798:E / AndroidRuntime(776):com.android.internal.os.ZygoteInit.main(ZygoteInit.java:602)
02-26 11:57:50.798:E / AndroidRuntime(776):dalvik.system.NativeStart.main(ネイティブメソッド)
02-26 11:57:52.818:I / dalvikvm(776):threadid = 4:シグナル3に反応
02-26 11:57:52.818:I / dalvikvm(776):スタックトレースを「/data/anr/traces.txt」に書き込みました

したがって、フラグメントの同じインスタンスを配置する代わりに、これを再作成して問題を修正することはできますが、効率的ではないようです。

transaction.replace(R.id.layout_tablet_paneau, LigneMessageTabletFragment.newInstance());
于 2013-02-26T11:14:18.320 に答える
2

あなたのエラーはandroid.view.InflateExceptionですか?

その場合は、Fragment を動的にインフレートする必要があります。XML レイアウトは使用しないでください。

また、XML Layout で定義されているフラグメントを Fragment Transaction の対象にしないでください。

于 2013-02-18T05:32:58.043 に答える
-1

このリンクの 32 番を確認してください。

親 Fragment をデタッチした後も保持される子 FragmentManager

手順:

  1. このクラスをダウンロードしてプロジェクトにコピーします
  2. サポート v4 one を使用してすべての Fragment を拡張します (ベスト プラクティス)
  3. FragmentStatePagerAdapter の代わりにそのクラスを使用します
于 2015-12-15T10:35:40.197 に答える