2016-11-17 1 views
2

私はアプリケーションに適切なバックスタッキングを実装するいくつかの問題があります。私は自分が何をやっているのか分かっていたと思っていましたが、それは偶然のためにしか働かないことが判明しました。フラグメントBackstacking正しく

これは、GoogleがAndroidスタジオで提供するテンプレートを使用しています。

まず、私の設定は次のようになります。私content_main.xmlは次のように設定:私の主な活動で

<RelativeLayout 
xmlns:android="http://schemas.android.com/apk/res/android" 
....> 
<FrameLayout 
    .... 
    android:id="@+id/mainFrame"></FrameLayout> 
</RelativeLayout> 

、私はこのようなIDを取り込むことにより、断片を切り換え機能を持っている:

(私はアンドロイドを使用してから、いくつかのたるみを得る病気おそらく知っています。 app.Fragmentではサポートライブラリではなく、私が原因を助けてくれるかどうかを切り換えるつもりですが、別の問題に遭遇します。答えが「サポートライブラリに切り替える」ことが判明した場合)

private void drawFragmentFromId(int id) 
{ 
    android.app.Fragment currentFragment = fm.findFragmentById(R.id.mainFrame); 
    if (id == R.id.nav_overview) 
    { 
     //fm is a global fragment manager, is that bad practice? 
     if(currentFragment.getTag() == "F_SETTINGS") 
      fm.beginTransaction().replace(currentFragment.getId(), oFrag, "F_OVERVIEW").commit(); 
     else 
      fm.beginTransaction().replace(currentFragment.getId(), oFrag, "F_OVERVIEW").addToBackStack(currentFragment.getTag()).commit(); 
    } 
.... 
} 

私はif(currentFragment.getTag() == "F_SETTINGS")理想的には、バックグラウンドに設定フラグメントを追加したくないからです。つまり、ユーザーがオーバービューフラグメントに行き、設定フラグメント、フラグメント 'foo'をたどってから、戻るボタンを押すと、理想的には、アプリケーションが設定フラグメントに戻ることを望みませんが、スキップしますそれは完全に。私がここで何か間違っているのか、それを行う良い練習方法があれば私に教えてください。

私のonBackPressedでは、super.onBackPressed()に過去の断片の描画を扱わせてもらいました。

これは、何らかの理由で、アプリがクラッシュすることがあり、既に描画されているフラグメントを描画しようとしていることを伝えています。正確には:私は、例えば、概要フラグメントに移動しようと

java.lang.IllegalStateException: Fragment already added: OverviewFragment{7ee61cf #0 id=0x7f0d0072 F_OVERVIEW}

アプリがクラッシュするようで、その後の設定は、再び概観した後、[戻る]ボタンを押してください。しかし、バックグラウンドに設定フラグメントを追加すると、このプロセスは完全にうまくいくように見えます。

私は概要の断片に行き、次に別の断片、それを 'foo'と呼ぶと、アプリは本当に変わったことをしますが、必要に応じて設定断片をスキップしますが、 fooフラグメントをオーバービューフラグメントと組み合わせると、オーバービューフラグメントが上に置かれます。

私はアプリのデフォルトonBackPressed()に問題があると推測しています。おそらく、新しいものと置き換えるべき断片はわからないかもしれませんが、正直言って、私はこれをどう修正するかという手がかりはありません。

ご協力いただければ幸いです。これを読んでいただきありがとうございます。

EDIT: 全体logcatのスタックトレース:

11-16 15:22:26.948 24151-24151/com.projects.mocks.mocks E/AndroidRuntime: FATAL EXCEPTION: main 
                     Process: com.projects.mocks.mocks, PID: 24151 
                     java.lang.IllegalStateException: Fragment already added: OverviewFragment{134836e #0 id=0x7f0d0072 F_OVERVIEW} 
                      at android.app.FragmentManagerImpl.addFragment(FragmentManager.java:1219) 
                      at android.app.BackStackRecord.popFromBackStack(BackStackRecord.java:1630) 
                      at android.app.FragmentManagerImpl.popBackStackState(FragmentManager.java:1587) 
                      at android.app.FragmentManagerImpl.popBackStackImmediate(FragmentManager.java:578) 
                      at android.app.Activity.onBackPressed(Activity.java:2503) 
                      at android.support.v4.app.FragmentActivity.onBackPressed(FragmentActivity.java:180) 
                      at com.projects.mocks.mocks.MainActivity.onBackPressed(MainActivity.java:143) 
                      at android.app.Activity.onKeyUp(Activity.java:2477) 
                      at android.view.KeyEvent.dispatch(KeyEvent.java:2664) 
                      at android.app.Activity.dispatchKeyEvent(Activity.java:2730) 
                      at android.support.v7.app.AppCompatActivity.dispatchKeyEvent(AppCompatActivity.java:543) 
                      at android.support.v7.view.WindowCallbackWrapper.dispatchKeyEvent(WindowCallbackWrapper.java:53) 
                      at android.support.v7.app.AppCompatDelegateImplBase$AppCompatWindowCallbackBase.dispatchKeyEvent(AppCompatDelegateImplBase.java:315) 
                      at android.support.v7.view.WindowCallbackWrapper.dispatchKeyEvent(WindowCallbackWrapper.java:53) 
                      at com.android.internal.policy.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:2310) 
                      at android.view.ViewRootImpl$ViewPostImeInputStage.processKeyEvent(ViewRootImpl.java:4127) 
                      at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4089) 
                      at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3642) 
                      at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3695) 
                      at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3661) 
                      at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3787) 
                      at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3669) 
                      at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:3844) 
                      at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3642) 
                      at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3695) 
                      at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3661) 
                      at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3669) 
                      at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3642) 
                      at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3695) 
                      at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3661) 
                      at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3820) 
                      at android.view.ViewRootImpl$ImeInputStage.onFinishedInputEvent(ViewRootImpl.java:3981) 
                      at android.view.inputmethod.InputMethodManager$PendingEvent.run(InputMethodManager.java:2253) 
                      at android.view.inputmethod.InputMethodManager.invokeFinishedInputEventCallback(InputMethodManager.java:1874) 
                      at android.view.inputmethod.InputMethodManager.finishedInputEvent(InputMethodManager.java:1865) 
                      at android.view.inputmethod.InputMethodManager$ImeInputEventSender.onInputEventFinished(InputMethodManager.java:2230) 
                      at android.view.InputEventSender.dispatchInputEventFinished(InputEventSender.java:141) 
                      at android.os.MessageQueue.nativePollOnce(Native Method) 
                      at android.os.MessageQueue.next(MessageQueue.java:323) 
                      at android.os.Looper.loop(Looper.java:135) 
                      at android.app.ActivityThread.main(ActivityThread.java:5417) 
                      at java.lang.reflect.Method.invoke(Native Method) 
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 
+0

logcat – Karakuri

+0

編集した質問から完全なスタックトレースを投稿してください。 –

答えて

0

ルックの私は自分の所望の効果を考え出したよう。そして、私はこれと同じ問題に直面しているかもしれない誰かの答えとしてこれを投稿します。

私のコードは正しかったようですが、コード全体が期待どおりに機能するように、ちょっとしたコードが欠落していました。

上記のコードの問題は、私がこの効果を達成しようとしていることです。 ユーザーは[A]をクリックし、次に[C]をクリックしてから、他のフラグメント、[B] バックスタッキングに[C]を追加していないので、逆転を行うときにonBackPressed()は[C]をスキップすると思うでしょうが、バックスタックの仕組みは「状態スナップショット」のようなものですその正確な状態をリロードしてください。バックスタックに[C]を追加しないので、わかっていることは[A]を再追加することですが、[B]は決して削除されません。

ソリューションは、次の操作を実行することでした。

private void drawFragmentFromId(int id) 
{ 
    android.app.Fragment currentFragment = fm.findFragmentById(R.id.mainFrame); 
    if (id == R.id.nav_overview) 
    { 
     //fm is a global fragment manager, is that bad practice? 
     if(currentFragment.getTag() == "F_SETTINGS"){ 
//------------------------------------------------------------------------------- 
      fm.popBackStack(); //it was this guy here. that's all I was missing. 
//------------------------------------------------------------------------------- 
      fm.beginTransaction().replace(currentFragment.getId(), oFrag, "F_OVERVIEW").commit(); 
     } 
     else 
      fm.beginTransaction().replace(currentFragment.getId(), oFrag, "F_OVERVIEW").addToBackStack(currentFragment.getTag()).commit(); 
    } 
.... 
} 

It was this answer that pointed me in the right direction.(さらに少しダウン、それは冗長な答えだ)

関連する問題