2

Ich habe Probleme mit den Instanzen ViewPager und Fragment.ViewPager enthält die Instanz des Fragments auch nach dem Setzen eines neuen Adapters

Ich habe eine ViewPager (nennen wir Vater) mit 4 Fragmenten und in das letzte Fragment habe ich eine weitere ViewPager (und nennen Sie Child) mit dynamischen Fragmenten Betrag. Was ich meine ist, dass ich das Kind basierend auf einer Liste von Objekten im Speicher erstelle. Wenn also die Liste 3 Objekte enthält, enthält das Kind 3 Fragmente. Wenn in einem bestimmten Moment etwas passiert und ich eine Liste mit einem Objekt erhalte, muss ich das Kind mit nur einem Fragment aktualisieren. Ein wichtiger Punkt hier ist, dass jedes Kind Fragment sein eigenes Objekt aus der zurückgegebenen Liste hat und basierend auf diesem Objekt erstellt wird.

Der Code, den ich ViewPager die Liste der Fragmente in das Kind zu setzen tun ist folgende:

@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 
     } 
    } 
} 

Bitte beachte, dass ich versuche, den gleichen Adapters Instanz zu verwenden, um die Fragmente zu setzen und dann die Änderungen benachrichtigen (notifyDataSetChanged() ist in der Methode). Wenn ich die Instanz des Adapters nicht erhalte, erstelle ich eine neue und setze sie auf ViewPager Kind.

Das Problem passiert zum Beispiel, wenn ich die ViewPager Child mit 2 Fragmenten und nach einer Weile muss ich es mit 1 Fragment setzen. Die ViewPager zeigt nur 1 Fragment darin, aber die zweite ist immer noch angebracht und wird nicht zerstört. Ich weiß es, weil ich einen Test gemacht habe, der getChildFragmentManager().getFragments() aufruft, und ich konnte das Fragment sehen, das zerstört werden sollte, ist noch dort.

Sie können sagen, dass es nicht wirklich ein Problem ist, da die Garbage Collector die unbenutzte Fragment entfernen kann. Wenn ich zum Beispiel in einem Moment versuche, 2 neue Fragmente wieder in das ViewPager Child zu setzen, verwendet es diese unbenutzte Fragment Instanz, anstatt eine neue Instanz zu erstellen, und leider verwendet es auch dasselbe Objekt und nicht das richtige neue.

Das ist mein DefaultStateViewPagerAdapter Code:

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); 
    } 

} 

ich bereits versucht saveState, um außer Kraft zu setzen, die ViewPager verwendet die alte fragment's Instanz zu vermeiden, wie:

@Override 
public Parcelable saveState() { 
    return null; 
} 

Es funktionierte, und Die ViewPager verwendet nicht mehr die alte Referenz, aber die unbenutzte Fragment ist immer noch angeschlossen, und es verursacht Speicherverlust.

Ich weiß nicht, warum die ViewPager ihre Fragmente nicht zerstört, auch nachdem ich einen neuen Adapter gesetzt habe. Hat jemand dieses Problem jemals gehabt?

Antwort

0

Ich fand die Lösung.

Die Lösung ist sehr einfach. Ich musste nur manuell null auf den Adapter des Kindes setzen. Damit ist die ViewPager gezwungen, jedes Fragment zu zerstören.

So in die onDestroyView von Fragment ‚s Vater fügte ich hinzu:

@Override 
public void onDestroyView() { 
    super.onDestroyView(); 
    mViewpagerChild.removeOnPageChangeListener(mOnPaymentMethodsPageChangeListener); 
    mViewpagerChild.setAdapter(null); // <-- This is what I added 
} 
Verwandte Themen