2

ViewPagerFragmentのインスタンスに問題があります。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が新しいアダプタを設定した後でも、そのフラグメントを破棄しない理由はわかりません。誰もこの問題を抱えていましたか?

答えて

0

解決策が見つかりました。

解決策は非常に簡単です。私はちょうど手動で子のアダプターにnullを設定しなければなりませんでした。これにより、ViewPagerはすべてのフラグメントを強制的に破棄します。

だからFragmentの父親のonDestroyViewに私が追加:

@Override 
public void onDestroyView() { 
    super.onDestroyView(); 
    mViewpagerChild.removeOnPageChangeListener(mOnPaymentMethodsPageChangeListener); 
    mViewpagerChild.setAdapter(null); // <-- This is what I added 
} 
関連する問題