2012-03-28 15 views
22
のID

Androidプラットフォームに変更することはできません:3.1はIllegalStateException:コンテナ断片

を、私はここで、コンテナBに容器Aからの断片を移動しようとしていますが、これを達成するためのコードを、次のとおりです。

private void reattach(int newContainerId, Fragment frag, String tag) { 

     if (frag == null || !frag.isAdded() || (frag.getId() == newContainerId)) { return; } 

     final FragmentManager fm = getFragmentManager(); 
     FragmentTransaction ft = fm.beginTransaction(); 
     ft.remove(frag);  //stacco il frammento dal container A 
     ft.commit(); 
     fm.executePendingTransactions(); 

     ft = fm.beginTransaction(); 
     ft.add(newContainerId, frag, tag); //attacco il frammento sul container D 
     ft.commit(); 
     fm.executePendingTransactions(); 
    } 
私はシステムを実行すると、私は次のようIllegalStateExceptionを取得

:迅速なデバッグ後

03-26 00:13:14.829: E/AndroidRuntime(30090): java.lang.RuntimeException: Unable to start activity ComponentInfo{eu.areamobile.apps.sfa/eu.areamobile.apps.sfa.activity.HomeActivity}: java.lang.IllegalStateException: Can't change container ID of fragment FragmentHomeController{408202a8 id=0x7f050010 HomeController}: was 2131034128 now 2131034132 
03-26 00:13:14.829: E/AndroidRuntime(30090): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1751) 
03-26 00:13:14.829: E/AndroidRuntime(30090): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1767) 
03-26 00:13:14.829: E/AndroidRuntime(30090): at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3117) 
03-26 00:13:14.829: E/AndroidRuntime(30090): at android.app.ActivityThread.access$1600(ActivityThread.java:122) 
03-26 00:13:14.829: E/AndroidRuntime(30090): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1009) 
03-26 00:13:14.829: E/AndroidRuntime(30090): at android.os.Handler.dispatchMessage(Handler.java:99) 
03-26 00:13:14.829: E/AndroidRuntime(30090): at android.os.Looper.loop(Looper.java:132) 
03-26 00:13:14.829: E/AndroidRuntime(30090): at android.app.ActivityThread.main(ActivityThread.java:4028) 
03-26 00:13:14.829: E/AndroidRuntime(30090): at java.lang.reflect.Method.invokeNative(Native Method) 
03-26 00:13:14.829: E/AndroidRuntime(30090): at java.lang.reflect.Method.invoke(Method.java:491) 
03-26 00:13:14.829: E/AndroidRuntime(30090): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:844) 
03-26 00:13:14.829: E/AndroidRuntime(30090): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:602) 
03-26 00:13:14.829: E/AndroidRuntime(30090): at dalvik.system.NativeStart.main(Native Method) 
03-26 00:13:14.829: E/AndroidRuntime(30090): Caused by: java.lang.IllegalStateException: Can't change container ID of fragment FragmentHomeController{408202a8 id=0x7f050010 HomeController}: was 2131034128 now 2131034132 
03-26 00:13:14.829: E/AndroidRuntime(30090): at android.app.BackStackRecord.doAddOp(BackStackRecord.java:338) 
03-26 00:13:14.829: E/AndroidRuntime(30090): at android.app.BackStackRecord.add(BackStackRecord.java:316) 
03-26 00:13:14.829: E/AndroidRuntime(30090): at eu.areamobile.apps.sfa.activity.HomeActivity.reattach(HomeActivity.java:340) 
03-26 00:13:14.829: E/AndroidRuntime(30090): at eu.areamobile.apps.sfa.activity.HomeActivity.customHideShowCreate(HomeActivity.java:253) 
03-26 00:13:14.829: E/AndroidRuntime(30090): at eu.areamobile.apps.sfa.activity.HomeActivity.customHideShowCreate(HomeActivity.java:155) 
03-26 00:13:14.829: E/AndroidRuntime(30090): at eu.areamobile.apps.sfa.activity.HomeActivity.onPostCreate(HomeActivity.java:66) 
03-26 00:13:14.829: E/AndroidRuntime(30090): at android.app.Instrumentation.callActivityOnPostCreate(Instrumentation.java:1111) 
03-26 00:13:14.829: E/AndroidRuntime(30090): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1734) 

を、私は、Android 3.1にFragmentTransaction.removeがに設定されていないことに気づきました0はフラグメントのmContainerIdが削除され、ICSでは正しく機能します。
提案や回避策はありますか?それは述べてFragment Developer Guideに基づいて

+0

こんにちは!私は同じ問題を抱えています。これまでのシステムでこれを動作させることができましたか? – Anton

答えて

0

をあなたはaddToBackStack(呼び出さない場合)あなたはフラグメントを削除するトランザクションを実行する場合、そのフラグメントは、トランザクションがコミットされたときに破壊され、ユーザーがナビゲートすることはできませんそれに戻る。一方、あなたはaddToBackStackを呼んで行う場合の断片を除去するときに、ユーザーがバック

をナビゲートするのであれば、私はあなたのフラグ・オブジェクトが

に呼び出した後に破壊されていることを前提とし()、そしてフラグメントが停止され、再開されます
ft.remove(frag);  //stacco il frammento dal container A 
ft.commit(); 

しかし、それはICSで動作すると言いますが、これは奇妙です。 replaceメソッドを試してみてどうしたらいいのですか?

この情報がお役に立てば幸いです...

0

は(置き換える使用してみてください)を2回コミットを使用しないでくださいないmethod..If。

0

これは役に立たない場合は、後で何かをプロトタイプする必要がありますが、executePendingTransactions()を呼び出してもブロッキング呼び出しであってはならないため、別のトランザクションとして実行しないでくださいそれは、現在のコンテナにまだ存在しているかもしれない新しいコンテナにフラグメントを追加しようとすることを含め、コードの残りの部分が実行され始めるということです。

これをすべて1つの方法で実行しているので、削除を実行して1つのFragmentTransactionを追加すると、その順序で実行されることがわかります。フラグメントが1つのコンテナから削除されたことを知り、それを新しいコンテナに追加してからコミットすることができます。それ以外の場合は、2つの別々のトランザクションとして実際に実行したい場合は、基本フラグメントクラスにisRemoving()メソッドがあります。このメソッドは、フラグメントがコンテナから削除されているかどうかを通知し、falseになるまで待って、削除されました。つまり、トランザクションが実行される前に別のトランザクションが別のトランザクションに依存する場合、同期の問題を導入し始めています。単なるトランザクションとして削除したり追加したりする理由はありません。

おかげで、 デビッド

+0

私はこれを試した - それは動作しません。 –

18

この問題に対する私のソリューションは、その状態に保ちながら、フラグメントを再作成することです:

private Fragment recreateFragment(Fragment f) 
    { 
     try { 
      Fragment.SavedState savedState = mFragmentManager.saveFragmentInstanceState(f); 

      Fragment newInstance = f.getClass().newInstance(); 
      newInstance.setInitialSavedState(savedState); 

      return newInstance; 
     } 
     catch (Exception e) // InstantiationException, IllegalAccessException 
     { 
      throw new RuntimeException("Cannot reinstantiate fragment " + f.getClass().getName(), e); 
     } 
    } 

それを次のヘルパー関数で

FragmentTransaction ft = mFragmentManager.beginTransaction(); 
ft.remove(old); 
Fragment newInstance = recreateFragment(old); 
ft.add(R.id.new_container, newInstance); 
ft.commit(); 

を少なくとも私はまだ最新のサポートライブラリ(r11)で動作していますが、まだあまりテストはしていませんでした。

追加コストは、フラグメントを2回インスタンス化することです。

+0

私は、インスタンス化例外を取得しています。それを解決する方法?詳細なしで言うことは不可能です –

+0

@RethinavelPillai。 – sstn

+0

デバイスの回転場合、私はこのコードを貼り付けることができますか? – Tomas

12

同様の質問からすべての回答を試した後、私はそのトリックを行う方法を見つけたようです。

まず問題 - あなたが本当にに持ってをコミットし、別の容器にフラグメントを追加しようとする前に、削除トランザクションを実行します。それはありがとうございますnave's answer

しかし、これは毎回動作しません。 2番目の問題はバックスタックです。それは何とかトランザクションをブロックします。以下のようなので、私の作品の完全なコードは、見え

:二度目のフラグメントを追加する前に、私は同様の問題があったとmanager.executePendingTransactionsを呼び出す

manager.popBackStackImmediate(null, FragmentManager.POP_BACK_STACK_INCLUSIVE); 
manager.beginTransaction().remove(detailFragment).commit(); 
manager.executePendingTransactions(); 
manager.beginTransaction() 
    .replace(R.id.content, masterFragment, masterTag) 
    .add(R.id.detail, detailFragment, activeTag) 
    .commit();    
1

は()私のためのトリックを行いました。 ありがとう!

0

プログラミングの貧弱さに加えて、有効な理由はありますか?それでも、既存のフラグメントを1つのアクティビティに含めるか、2つの既存のフラグメントを参照しておきたいですか?フラグメントの状態を保存して単純に再作成するのではなく、

私が使用してフラグメントを作成した

public static ContactsFragment mContactsFragment; 

    public static ContactsFragment getInstance() { 
    if (mContactsFragment == null) { 
     mContactsFragment = new ContactsFragment(); 
    } 
    return mContactsFragment; 
} 

私はAndroidの学んだので、これをやったが、私はそれがみんなの例であるにも関わらず、静的に私のフラグメントを参照したいと思いますなぜ見ることができません。もともとContextを静的に参照することだと思っていましたが、新しいフラグメントを作成してコンテキストを保存するといつでもこれを設定できます。とにかく後で奇妙なバグにつながることがよくあります。

なぜあなたはないでしょう:

public static ContactsFragment newInstance(Context c) { 
    ContactsFragment mContactsFragment = new ContactsFragment(); 
    mContext = c; 
    return mContactsFragment; 
} 

と、単にあなたがフラグメントに行ってきたすべての作業を保存し、あなたは再びそれを必要なときにそれを再作成しますか? おそらく私はあなたが100 +(ニュースアプリ?)を作成していたのではなく、毎回作成する必要がなく、メモリに保存したいと思うかもしれないと思いますか?誰でも?

0

私は同じ問題を抱えていて、別のやり方で問題を解決しました。私のアプリケーションには4つの断片があり、自分のデバイスが横長モードのときに管理する必要があります。レシピ(レシピのリストが含まれている) 2 - - 成分(のリスト 1:私は私のアプリでは4つの断片を持っている

私のアプリ:

私は私のアプリと解決策を説明しましょう選択レシピから食材) 3 - ステップ(ステップのリスト) 4 - プレイヤー(ビデオを再生するために呼ばれていますフラグメント)

ポートレートモードでは、私は何の問題もなかった、すべてが正常に動作します!

風景 私の活動は私の破片のための2個のコンテナを持って、左側ウィッヒの一つが右側に私のレシピのリスト、および他が含まれています。このコンテナは右側にあり、動的に変化します。

私は、ポートレートモードで、私のフラグメントが表示されている、と私は私のデバイスを回転させたときに、私は細部のコンテナに移動するには見せていた同じフラグメントをしたいとき、この問題を抱えています。 それで、すべての私の問題が始まった。

マイソリューション

  1. 保存最後の断片は、可変に示しました。
  2. StateフラグメントをonSavedInstanceに保存します。 onCreateで
  3. は、フラグメントを取得し、最後のフラグメントを示しました。だから、

、私はこのヘルプ誰 https://gist.github.com/jillesRagonha/4c184165b92fdf026ab3cd033b64b1bf

希望を支援するために、この要旨を作成し、よりespecificすべき:D