ViewPager
とFragment
のインスタンスに問題があります。ViewPagerは新しいアダプタを設定してもフラグメントのインスタンスを保持します
私は(父と呼ぶことにしましょう)と4つのフラグメントを持ち、最後のフラグメントにはもう1つのViewPager
(そしてそれをChildと呼んでいます)を動的フラグメント量で持っています。つまり、メモリ内のオブジェクトのリストに基づいて子を作成するということです。したがって、リストに3つのオブジェクトが含まれている場合、その子は3つのフラグメントを内部に持つことになります。確定した瞬間に何かが起こって、1つのオブジェクトのリストが得られたら、私はちょうど1つのフラグメントで子を更新する必要があります。ここで重要な点は、各子のFragment
には、返されたリストの独自のオブジェクトがあり、このオブジェクトに基づいて作成されている点です。
私は子供ViewPager
にフラグメントのリストを設定するために行うコードは次のとおりです。私は断片を設定し、変更を通知するために、同じアダプタのインスタンスを使用しようと
@Override
public void setViewPagerChildFragments(List<Fragment> fragments) {
if (fragments != null) {
DefaultStateViewPagerAdapter adapter = (DefaultStateViewPagerAdapter) mViewpagerChild.getAdapter();
if (adapter == null) {
/* In this case I use getChildFragmentManager() because
it's inside the last fragment of the ViewPager Father*/
adapter = new DefaultStateViewPagerAdapter(getChildFragmentManager(), fragments);
mViewpagerChild.setAdapter(adapter);
} else {
adapter.setFragments(fragments); // Into this method I do notifyDataSetChanged() already
}
}
}
注意(notifyDataSetChanged()
メソッド内にあります)。アダプタのインスタンスが取得できない場合は、新しいインスタンスを作成してViewPager
子に設定します。
問題は、例えば、私がViewPager
子を2つのフラグメントで設定し、しばらくして1つのフラグメントで設定する必要がある場合に発生します。 ViewPager
はその中にただ1つの断片を示していますが、2番目の断片はまだ添付されており、破棄されません。 getChildFragmentManager().getFragments()
というテストをしたので、私はそれを知っています。破壊されるはずの断片がまだ残っているのがわかりました。
Garbage Collector
は、未使用のFragment
を削除できるので、実際には問題ではないと言えます。しかし、たとえばある時点で、2つの新しいフラグメントをViewPager
子に再度設定しようとすると、その新しい未使用のFragment
インスタンスが使用されますが、残念ながら正しいオブジェクトではなく同じオブジェクトが使用されます。
public class DefaultStateViewPagerAdapter extends FragmentStatePagerAdapter {
private ArrayList<Fragment> mFragments;
private ArrayList<String> mFragmentTitles;
public DefaultStateViewPagerAdapter(FragmentManager fm) {
super(fm);
this.mFragments = new ArrayList<>();
this.mFragmentTitles = new ArrayList<>();
}
public DefaultStateViewPagerAdapter(FragmentManager fm, List<Fragment> fragments) {
super(fm);
this.mFragments = (ArrayList<Fragment>) fragments;
}
@Override
public Fragment getItem(int position) {
return mFragments.get(position);
}
@Override
public int getItemPosition(Object object) {
int index = mFragments.indexOf(object);
if (index < 0) {
index = POSITION_NONE;
}
return index;
}
@Override
public int getCount() {
return mFragments.size();
}
@Override
public CharSequence getPageTitle(int position) {
return mFragmentTitles.get(position);
}
public void clearFragments() {
mFragments.clear();
mFragmentTitles.clear();
}
public void setFragments(List<Fragment> fragments) {
mFragments = (ArrayList<Fragment>) fragments;
notifyDataSetChanged();
}
public void addFragment(Fragment fragment, String title) {
mFragments.add(fragment);
mFragmentTitles.add(title);
}
}
私はすでにViewPager
を避けるためにsaveState
を上書きしようとしたように、古いfragment'sインスタンスを使用しています:それは働いた
@Override
public Parcelable saveState() {
return null;
}
、および
これは私のDefaultStateViewPagerAdapter
コードですViewPager
は古い参照を使用しなくなりましたが、未使用のFragment
はまだ接続されており、メモリリークの原因となります。
ViewPager
が新しいアダプタを設定した後でも、そのフラグメントを破棄しない理由はわかりません。誰もこの問題を抱えていましたか?