FragmentManager#getFragments()で取得するListの要素がnullになっていたのでFrameworkのソースコードを読んでみた
FragmentManager#getFragments() の挙動がなんか思っていたのと違ったので調べてみたメモ。
具体例を挙げると、Fragment A
がattachされている状態で、Fragment B
をFragmentTransaction#add() -> remove() した時に、
FragmentManager#getFragments() で得られるリストの要素数は1だと思ったけど、残念2でした〜〜という話。
0番目には予想どおり Fragment A
が、1番目にはnullが入っていた。removeしたって言ったじゃないか。解せぬ。
というわけでいつも通りFrameworkのコードを読んでいきます。まずはgetFragments() で何が返ってきているのか確認。
ArrayList<Fragment> mActive; @Override public List<Fragment> getFragments() { return mActive; }
この mActive
って名前のArrayListにactiveな状態のfragmentが管理されていそうなもんなのに、なんでactiveでなくなったfragmentを保持していたであろう要素がremoveされずにnullになっているのか?
activeじゃなくなる時のコードを見てみましょう。
void makeInactive(Fragment f) { if (f.mIndex < 0) { return; } if (DEBUG) Log.v(TAG, "Freeing fragment index " + f); mActive.set(f.mIndex, null); if (mAvailIndices == null) { mAvailIndices = new ArrayList<Integer>(); } mAvailIndices.add(f.mIndex); mHost.inactivateFragment(f.mWho); f.initState(); }
ここでnullがセットされています。
気になるのはその下、 mAvailIndices
にinactiveになったfragmentのindexがaddされているところですね。
mAvailIndices
はIntergerのArrayListで、
ArrayList<Integer> mAvailIndices;
使われるのはFragmentがactiveになった時。
void makeActive(Fragment f) { if (f.mIndex >= 0) { return; } if (mAvailIndices == null || mAvailIndices.size() <= 0) { if (mActive == null) { mActive = new ArrayList<Fragment>(); } f.setIndex(mActive.size(), mParent); mActive.add(f); } else { f.setIndex(mAvailIndices.remove(mAvailIndices.size()-1), mParent); mActive.set(f.mIndex, f); } if (DEBUG) Log.v(TAG, "Allocated fragment index " + f); }
mAvailIndices
Listの最後の要素をactiveにしたいfragmentのindexにセットしています。
つまり、 removeしたfragmentのindexを mAvailIndices
に退避しておいて、
次にaddなりしてactiveになったfragmentにそのindexを割り当てるということをしています。
例えば、 3つのFragmentがActiveな場合、
index | Fragment |
---|---|
0 | A |
1 | B |
2 | C |
ここで Fragment B
をremoveすると、index 1 がnullになって、mAvailIndices
にindex 1 が退避されます。
index | Fragment |
---|---|
0 | A |
1 | null |
2 | C |
この状態で Fragment D
をaddすると、退避されていたindex 1 が使用される。
index | Fragment |
---|---|
0 | A |
1 | D |
2 | C |
indexの効率化が目的だったのかなー。