wake-up-neo.net

Viewpager-Fragmente werden nach dem ersten Mal nicht angezeigt

Ich habe eine Aktivität mit 3 Fragmenten (A, B, C). Fragment A besteht aus einem ViewPager mit 2 ListFragments. Der Benutzer kann in einem der Listfragments auf ein Element tippen und wechselt dadurch zu Fragment B.

In Fragment A mache ich:

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
    pagerAdapter = new PagerAdapter(getActivity().getSupportFragmentManager());
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragmentA, container, false);

    vpPager = (ViewPager)view.findViewById(R.id.vpPager);
    vpPager.setOffscreenPageLimit(2);
    vpPager.setAdapter(pagerAdapter);
    vpPager.addOnPageChangeListener(this);

    return view;
}

Und das PagerAdapter lautet wie folgt:

private class PagerAdapter extends FragmentPagerAdapter {
    private final ListFragment1 lf1 = ListFragment1 .newInstance();
    private final ListFragment2 lf2 = ListFragment2 .newInstance();

    public PagerAdapter(Android.support.v4.app.FragmentManager fm) {
        super(fm);
    }

    @Override
    public Android.support.v4.app.Fragment getItem(int position) {
        switch (position) {
            case 0:  return lf1;
            case 1:  return lf2;
            default: return null;
        }
    }
}

Wenn die Aktivität zum ersten Mal angezeigt wird, werden die Viewpager-Listenfragmente korrekt angezeigt. 

Die 2 Viewpager-Fragmente laden Daten aus einer Datenbank, und ich mache dies nur einmal (wenn die Fragmente erstellt werden).

Der Benutzer kann auf ein Element tippen und Fragment B wird angezeigt. Wenn der Benutzer Zurück drückt, wird Fragment A angezeigt. Die Listenfragmente werden jedoch nicht angezeigt (bereits existiert eine Instanz davon).

Könnte es sein, dass die Sicht zerstört wurde, obwohl Instanzen existieren?

Was ist hier falsch? Gibt es einen besseren Ansatz?

EDIT 

Wenn ich newInstance im Pageradapter verwende, erhalte ich einen IllegalStateException: not attached to activity. Dies liegt daran, dass ich eine asynchrone Aufgabe wie folgt starte:

@Override
public void onPageSelected(int position) {
    Fragment fragment = pagerAdapter.getItem(position);
    if (fragment instanceof IPagedFragment) {
        ((IPagedFragment) fragment).onShown();
    }
}

Und onShown ist:

@Override
public void onShown() {
    myTask= new MyTask();
    myTask.execute((Void)null);
}

Wann kann ich die Aufgabe starten, sodass ich 100% sicher bin, dass das Fragment an die Aktivität angehängt ist und die Ansicht erstellt wurde (ich muss Listenansicht usw. vom Layout abrufen).

17

Sie müssen ChildFragmentManager wie unten verwenden.

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
    pagerAdapter = new PagerAdapter(getChildFragmentManager()); //here used child fragment manager 
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragmentA, container, false);

    vpPager = (ViewPager)view.findViewById(R.id.vpPager);
    vpPager.setOffscreenPageLimit(2);
    vpPager.setAdapter(pagerAdapter);
    vpPager.addOnPageChangeListener(this);

    return view;
}

Es funktioniert wie ein Zauber in meinem Code mit Viewpager und Fragment.

65
Darshan Mistry

Gerade jetzt habe ich es gelöst, nachdem ich mich den ganzen Tag gekämpft hatte, indem ich getChildFragmentManager() und es wird funktionieren.

bei der Verwendung von pagerAdapter im Fragment use:

PagerAdapter adapter = new PagerAdapter(getChildFragmentManager());

und im Falle einer Aktivität benutze getFragmentManager ()

PagerAdapter adapter = new PagerAdapter(getFragmentManager());
13
Gautam Kumar

Sie erstellen ListFragment1 und ListFragment2 mit Activity FragmentManager, während Sie Fragment FragmentManager verwenden sollten. Ändern Sie also die pagerAdapter = new PagerAdapter(getActivity().getSupportFragmentManager()); mit pagerAdapter = new PagerAdapter(getChildFragmentManager());. Auf diese Weise werden die Fragmente des View-Pagers an das Fragment gebunden, das den Viewpager hostet. Außerdem sollten Sie im Viewpager keinen Bezug auf Fragmente behalten, da dies bereits von Android verwaltet wird. Versuche es mit:

private class PagerAdapter extends FragmentPagerAdapter {

    public PagerAdapter(Android.support.v4.app.FragmentManager fm) {
        super(fm);
    }

    @Override
    public Android.support.v4.app.Fragment getItem(int position) {
        switch (position) {
            case 0:  return ListFragment1.newInstance();
            case 1:  return ListFragment2.newInstance();
            default: return null;
        }
    }
}

Übrigens ist vpPager.setOffscreenPageLimit(2); unbrauchbar, da Sie nur 2 Seiten haben. Diese Methode habe ich noch nie verwendet, selbst wenn ich viele Fragmente verwalten muss, da sie Speicher erfordert.

Informationen zu Ihrem Update: Entfernen Sie jegliche Logik, die sich auf ViewPager bezieht, das das Fragment verarbeitet. Wenn Sie eine AsyncTask in Ihrem Fragment starten müssen, können Sie dies mit einer der Methoden des Fragment-Lebenszyklus tun: onResume (), onCreateView () und so weiter.

class IPagedFragment extends Fragment {

    public void onResume() {
        super.onResume();
        myTask= new MyTask();
        myTask.execute((Void)null);
    }
}

und bitte entfernen Sie die private final ListFragment1 lf1 = ListFragment1 .newInstance();. Vertrauen Sie mir, es ist keine gute Idee, da Sie einen starken Bezug zu Ihren Fragmenten haben.

Ich habe ein einfaches Projekt erstellt, das Sie als Referenzimplementierung verwenden können. Sie können den Quellcode von meiner dropbox herunterladen.

12
Mimmo Grottoli

benutze getChildFragmentManager () anstelle von supportFragmentManager ()

0
Bayu

Versuchen Sie, die getItemPosition-Methode in Ihrem FragmentPagerAdapter zu überschreiben:

@Override
public int getItemPosition(Object object) {
    return PagerAdapter.POSITION_NONE;
}
0
Linh Nguyen

Wenn eine der oben genannten Lösungen nicht funktioniert, können Sie eine Problemumgehung versuchen, indem Sie (verzögert) einen zusätzlichen notifyDataSetChanged-Aufruf des Adapters an die Instanz der Pageransicht senden:

vpPager.post(new Runnable() {
    @Override
    public void run() {
        pagerAdapter.notifyDataSetChanged();
    }
});

oder

vpPager.postDelayed(new Runnable() {
    @Override
    public void run() {
        pagerAdapter.notifyDataSetChanged();
    }
}, 100 /* you have to find out the best delay time by trying/adjusting */);
0
Mehmed Mert