Fragmentページのロード混乱ビューの重複問題がどのように優雅に解決されるか
5317 ワード
[Vio.wangはオープンソース歓迎コメントを尊ぶ]もともとこの問題を問題フィードバックに記載しようとしたが、触れた面が大きいと感じたら、1編だけ書きましょう.実はこれもよくある問題ですが、アプリが回収された後、再びフロントに戻るとページActivityが再ロードされ、その中には必ずonSaveInstanceState()とonRestoreInstanceState()の2つの方法が含まれています.最初にこの問題に気づいたのも驚くべきことで、これもgoogleが考えていなかったのではないでしょうか.ネット上ではこの問題について,(1)onSaveInstanceStateメソッドを書き換え,親を呼び出すメソッドを乾かす2つの解決策がある.この手は毒辣で,釜の底から給料を引き上げ,優雅さを失わない.
親がどのように処理しているのか、なぜそれを乾かす必要があるのかを見てみましょう.
ActivityがFragmentActivityを継承しているため、FragmentActivityではデフォルトでサブメソッドが実行され、ページが回収されたときにロードされたすべてのfragment状態が保存されます.そのonCreate()を見てみましょう
FragmentActivityのonCreateでは、現在保存されているfragmentがデフォルトで復元されます.ここでfragmentのロードが混乱している根本的な原因がわかります.FragmentActivityは現在のfragmentを管理してくれましたが、私たちは自分のActivityで判断せずに直接ビューを追加したので、明らかに問題が発生します.私が判断したと言うかもしれませんが、2つ目の解決策を見てみましょう.(2)2つ目の方法は、getSupportFragmentManagerに追加されたfragmentを見つけることです.まずadd Fragmentで次のメソッドを呼び出し、Fragmentにtagを追加します(tagはfragmentTagsの配列を推奨します).
そしてonCreateでsavedInstanceStateを判断!=nullは、tagに基づいてgetSupportFragmentManagerでfragmentを再取得します.たとえば、次のようにします.
これで問題も解決できますが、だめだという人がいるので、一二をたくさん試してみてください.(3)この方法は,いわば私を苦しめているが,プロジェクトは融雲を統合する必要があるため,融雲のセッションリストUIを直接多重化している.RCを統合した人は、RCのセッションリストのロード方式が動的Uriによってロードされていることを知っているかもしれません.これでは、1つ目の方法は使えません.RCと衝突し、2つ目の方法も理想的ではありません.問題も発生しました.ページが回収された後、セッションリストを空に再ロードします.ええ.森森さんが怪我をしました...そこで、getSupportFragmentManagerの管理戦略を検討しましたが、スタック内のすべてのfragmentをクリアし、再ロードすれば問題ないと思います.では、どうやってスタックを空にしますか?��http://stackoverflow.com/questions/6186433/clear-back-stack-using-fragmentsここに記録します:スタックを空にします:
あるfragment以上のfragmentを出す
次に、if(savedInstanceState!=null){}をすべて空にする必要があります.
問題はこれで解決する...
@Override
protected void onSaveInstanceState(Bundle outState) {
// super.onSaveInstanceState(outState);
outState.putInt("mLastIndex", mLastIndex);
}
親がどのように処理しているのか、なぜそれを乾かす必要があるのかを見てみましょう.
/**
* Save all appropriate fragment state.
*/
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Parcelable p = mFragments.saveAllState();
if (p != null) {
outState.putParcelable(FRAGMENTS_TAG, p);
}
}
ActivityがFragmentActivityを継承しているため、FragmentActivityではデフォルトでサブメソッドが実行され、ページが回収されたときにロードされたすべてのfragment状態が保存されます.そのonCreate()を見てみましょう
if (savedInstanceState != null) {
Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG);
mFragments.restoreAllState(p, nc != null ? nc.fragments : null);
}
mFragments.dispatchCreate();
FragmentActivityのonCreateでは、現在保存されているfragmentがデフォルトで復元されます.ここでfragmentのロードが混乱している根本的な原因がわかります.FragmentActivityは現在のfragmentを管理してくれましたが、私たちは自分のActivityで判断せずに直接ビューを追加したので、明らかに問題が発生します.私が判断したと言うかもしれませんが、2つ目の解決策を見てみましょう.(2)2つ目の方法は、getSupportFragmentManagerに追加されたfragmentを見つけることです.まずadd Fragmentで次のメソッドを呼び出し、Fragmentにtagを追加します(tagはfragmentTagsの配列を推奨します).
public abstract FragmentTransaction add(@IdRes int containerViewId, Fragment fragment,
@Nullable String tag);
そしてonCreateでsavedInstanceStateを判断!=nullは、tagに基づいてgetSupportFragmentManagerでfragmentを再取得します.たとえば、次のようにします.
aroundFragment = (AroundFragment) manager.findFragmentByTag(fragmentTags[0]);
これで問題も解決できますが、だめだという人がいるので、一二をたくさん試してみてください.(3)この方法は,いわば私を苦しめているが,プロジェクトは融雲を統合する必要があるため,融雲のセッションリストUIを直接多重化している.RCを統合した人は、RCのセッションリストのロード方式が動的Uriによってロードされていることを知っているかもしれません.これでは、1つ目の方法は使えません.RCと衝突し、2つ目の方法も理想的ではありません.問題も発生しました.ページが回収された後、セッションリストを空に再ロードします.ええ.森森さんが怪我をしました...そこで、getSupportFragmentManagerの管理戦略を検討しましたが、スタック内のすべてのfragmentをクリアし、再ロードすれば問題ないと思います.では、どうやってスタックを空にしますか?��http://stackoverflow.com/questions/6186433/clear-back-stack-using-fragmentsここに記録します:スタックを空にします:
FragmentManager fm = getActivity().getSupportFragmentManager();
for(int i = 0; i < fm.getBackStackEntryCount(); ++i) {
fm.popBackStack();
}
あるfragment以上のfragmentを出す
FragmentManager.popBackStack(XX.class.getName(), FragmentManager.POP_BACK_STACK_INCLUSIVE)
次に、if(savedInstanceState!=null){}をすべて空にする必要があります.
@Override
protected void init(Bundle savedInstanceState) {
setContentView(R.layout.activity_main);
FragmentManager manager = getSupportFragmentManager();
if (savedInstanceState != null) {
mLastIndex = savedInstanceState.getInt("mLastIndex", 0);
//fragmentmanager ConversationListFragment fragment
// manager.popBackStack(ConversationListFragment.class.getName(), FragmentManager.POP_BACK_STACK_INCLUSIVE);
for (int i = 0; i < manager.getBackStackEntryCount(); ++i) {
manager.popBackStack();
}
conversationListFragment = null;
......
}
問題はこれで解決する...