it-swarm.com.de

Aktualisieren Sie ViewPager dynamisch?

Ich kann den Inhalt in ViewPager nicht aktualisieren.

Eine Frage: In welcher Beziehung stehen die Methoden instantiateItem () und getItem () in der FragmentPagerAdapter-Klasse?

Ich habe nur getItem () verwendet, um meine Fragmente zu instanziieren und zurückzugeben:

@Override
public Fragment getItem(int position) {
    return new MyFragment(context, paramters);
}

Das hat gut funktioniert (aber wie gesagt, ich kann den Inhalt nicht ändern).

Also habe ich folgendes gefunden: ViewPager PagerAdapter aktualisiert die Ansicht nicht

Particulary One, in dem es um die Methode instantiateItem () geht:

"Mein Ansatz ist, die setTag () - Methode für jede instanziierte Ansicht in der instantiateItem () - Methode zu verwenden."

Also möchte ich jetzt instantiateItem () implementieren, um das zu tun. Aber ich weiß nicht, was ich dorthin zurückgeben muss (return ist Object) und wie ist die Beziehung zu getItem (int position)?

Derzeit verwende ich getItem, um das Fragment zu instanziieren. Ist das falsch? Muss ich dann die Fragmente in die Instanzvariable einfügen oder getItem () überhaupt nicht implementieren ...? Ich verstehe es einfach nicht.

Ich habe versucht die Referenz zu lesen :

  • public abstract Fragment getItem (int position)

    Gibt das Fragment zurück, das einer bestimmten Position zugeordnet ist.

  • public Object instantiateItem (ViewGroup-Container, int-Position)

    Erstellen Sie die Seite für die angegebene Position. Der Adapter ist für das Hinzufügen der Ansicht zu dem hier angegebenen Container verantwortlich, muss jedoch nur sicherstellen, dass dies bis zu der Zeit erfolgt, zu der er von finishUpdate (ViewGroup) ..__ zurückkehrt. Parameter

    container Die enthaltende Ansicht, in der die Seite angezeigt wird . position Die zu positionierende Seitenposition.

    Kehrt zurück

    Gibt ein Objekt zurück, das die neue Seite darstellt. Dies muss keine Ansicht sein, kann aber ein anderer Container der Seite sein.

... aber ich verstehe immer noch nicht, wie sie miteinander zusammenhängen und was ich tun muss.

Hier ist mein Code. Ich verwende das Unterstützungspaket v4.

ViewPagerTest 

public class ViewPagerTest extends FragmentActivity {
    private ViewPager pager;
    private MyFragmentAdapter adapter; 

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.pager1);

        pager = (ViewPager)findViewById(R.id.slider);

        String[] data = {"page1", "page2", "page3", "page4", "page5", "page6"};

        adapter = new MyFragmentAdapter(getSupportFragmentManager(), 6, this, data);
        pager.setAdapter(adapter);

        ((Button)findViewById(R.id.button)).setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                reload();
            }
        });
    }

    private void reload() {
        String[] data = {"changed1", "changed2", "changed3", "changed4", "changed5", "changed6"};
        //adapter = new MyFragmentAdapter(getSupportFragmentManager(), 6, this, data);
        adapter.setData(data);
        adapter.notifyDataSetChanged();
        pager.invalidate();

        //pager.setCurrentItem(0);
    }
}

MyFragmentAdapter

class MyFragmentAdapter extends FragmentPagerAdapter {
    private int slideCount;
    private Context context;
    private String[] data;

    public MyFragmentAdapter(FragmentManager fm, int slideCount, Context context, String[] data) {
        super(fm);
        this.slideCount = slideCount;
        this.context = context;
        this.data = data;
    }

    @Override
    public Fragment getItem(int position) {
        return new MyFragment(data[position], context);
    }

    @Override
    public int getCount() {
        return slideCount;
    }

    public void setData(String[] data) {
        this.data = data;
    }

    @Override
    public int getItemPosition(Object object) {
        return POSITION_NONE;
    }
}

MyFragment

public final class MyFragment extends Fragment {
    private String text;

    public MyFragment(String text, Context context) {
        this.text = text;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.slide, null);
        ((TextView)view.findViewById(R.id.text)).setText(text);

        return view;
    }
}

Hier ist auch jemand mit einem ähnlichen Problem, keine Antworten ...

http://www.mail-archive.com/[email protected]/msg200477.html

283
Ixx

Bei der Verwendung von FragmentPagerAdapter oder FragmentStatePagerAdapter ist es am besten, sich ausschließlich mit getItem() zu befassen und instantiateItem() überhaupt nicht zu berühren. Die Funktion instantiateItem()-destroyItem()-isViewFromObject() in PagerAdapter ist eine untergeordnete Schnittstelle, die FragmentPagerAdapter verwendet, um die wesentlich einfachere getItem()-Schnittstelle zu implementieren.

Bevor ich mich damit beschäftige, sollte ich das klarstellen 

Wenn Sie die tatsächlich angezeigten Fragmente austauschen möchten, müssen Sie FragmentPagerAdapter vermeiden und .__ verwenden. FragmentStatePagerAdapter.

In einer früheren Version dieser Antwort wurde der Fehler gemacht, FragmentPagerAdapter für sein Beispiel zu verwenden. Dies funktioniert nicht, da FragmentPagerAdapter ein Fragment niemals zerstört, nachdem es das erste Mal angezeigt wurde.

Ich empfehle nicht die Umgehung von setTag() und findViewWithTag() in dem von Ihnen verlinkten Post. Wie Sie herausgefunden haben, funktioniert die Verwendung von setTag() und findViewWithTag() nicht mit Fragmenten, daher ist dies keine gute Übereinstimmung.

Die richtige Lösung ist, getItemPosition() zu überschreiben. Wenn notifyDataSetChanged() aufgerufen wird, ruft ViewPager getItemPosition() für alle Elemente in seinem Adapter auf, um festzustellen, ob sie an eine andere Position verschoben oder entfernt werden müssen. 

Standardmäßig gibt getItemPosition()POSITION_UNCHANGED zurück, was bedeutet: "Dieses Objekt ist in Ordnung, wo es ist, zerstöre oder entferne es nicht." Die Rückgabe von POSITION_NONE behebt das Problem, indem er stattdessen sagt: "Dieses Objekt ist nicht mehr ein von mir angezeigtes Objekt. Entfernen Sie es." Auf diese Weise wird jedes einzelne Element in Ihrem Adapter entfernt und neu erstellt. 

Dies ist eine absolut legitime Lösung! Durch dieses Update verhält sich notifyDataSetChanged wie ein normaler Adapter ohne Ansichtsrecycling. Wenn Sie diesen Fix implementieren und die Leistung zufriedenstellend ist, gehen Sie zu den Rennen. Job erledigt.

Wenn Sie eine bessere Leistung benötigen, können Sie eine ausgefallenere getItemPosition()-Implementierung verwenden. Hier ein Beispiel für einen Pager, der Fragmente aus einer Liste von Strings erstellt:

ViewPager pager = /* get my ViewPager */;
// assume this actually has stuff in it
final ArrayList<String> titles = new ArrayList<String>();

FragmentManager fm = getSupportFragmentManager();
pager.setAdapter(new FragmentStatePagerAdapter(fm) {
    public int getCount() {
        return titles.size();
    }

    public Fragment getItem(int position) {
        MyFragment fragment = new MyFragment();
        fragment.setTitle(titles.get(position));
        return fragment;
    }

    public int getItemPosition(Object item) {
        MyFragment fragment = (MyFragment)item;
        String title = fragment.getTitle();
        int position = titles.indexOf(title);

        if (position >= 0) {
            return position;
        } else {
            return POSITION_NONE;
        }
    }
});

Bei dieser Implementierung werden nur Fragmente angezeigt, die neue Titel anzeigen. Fragmente mit Titeln, die sich noch in der Liste befinden, werden stattdessen an ihre neue Position in der Liste verschoben. Fragmente mit Titeln, die überhaupt nicht mehr in der Liste stehen, werden gelöscht.

Was ist, wenn das Fragment nicht neu erstellt wurde, aber trotzdem aktualisiert werden muss? Aktualisierungen eines lebendigen Fragments werden am besten vom Fragment selbst behandelt. Das ist der Vorteil eines Fragmentes - es ist ein eigener Controller. Ein Fragment kann einen Listener oder einen Beobachter zu einem anderen Objekt in onCreate() hinzufügen und es dann in onDestroy() entfernen, wodurch die Aktualisierungen selbst verwaltet werden. Sie müssen nicht den gesamten Aktualisierungscode in getItem() wie in einem Adapter für einen ListView- oder einen anderen AdapterView-Typ einfügen.

Eine letzte Sache - nur weil FragmentPagerAdapter kein Fragment zerstört, bedeutet dies nicht, dass getItemPosition in einem FragmentPagerAdapter völlig unbrauchbar ist. Sie können diesen Rückruf weiterhin verwenden, um Ihre Fragmente im ViewPager neu zu ordnen. Sie werden sie jedoch niemals vollständig aus dem FragmentManager entfernen.

571
Bill Phillips

Führen Sie Folgendes aus, anstatt POSITION_NONE von getItemPosition() zurückzugeben und eine vollständige Ansichtswiederherstellung zu bewirken:

//call this method to update fragments in ViewPager dynamically
public void update(UpdateData xyzData) {
    this.updateData = xyzData;
    notifyDataSetChanged();
}

@Override
public int getItemPosition(Object object) {
    if (object instanceof UpdateableFragment) {
        ((UpdateableFragment) object).update(updateData);
    }
    //don't return POSITION_NONE, avoid fragment recreation. 
    return super.getItemPosition(object);
}

Ihre Fragmente sollten die UpdateableFragment-Schnittstelle implementieren:

public class SomeFragment extends Fragment implements
    UpdateableFragment{

    @Override
    public void update(UpdateData xyzData) {
         // this method will be called for every fragment in viewpager
         // so check if update is for this fragment
         if(forMe(xyzData)) {
           // do whatever you want to update your UI
         }
    }
}

und die Schnittstelle:

public interface UpdateableFragment {
   public void update(UpdateData xyzData);
}

Ihre Datenklasse:

public class UpdateData {
    //whatever you want here
}
132
M-WaJeEh

für diejenigen, die immer noch das gleiche Problem haben, dem ich zuvor begegnet bin, wenn ich einen ViewPager mit 7 Fragmenten habe. Die Standardeinstellung für diese Fragmente zum Laden des englischen Inhalts aus dem API-Dienst, jedoch das Problem, dass ich die Sprache von den Einstellungen ändern möchte. Nach der Einstellung von Einstellungen möchte ich, dass ViewPager in der Hauptaktivität die Fragmente aktualisiert, um die Sprachauswahl zu erreichen vom Benutzer und laden Sie den arabischen Inhalt, wenn der Benutzer hier Arabisch auswählt, was ich von Anfang an gemacht habe 

1- Sie müssen FragmentStatePagerAdapter wie oben erwähnt verwenden.

2-on mainActivity Ich überschreibe das onResume und habe folgendes getan 

 if (!(mPagerAdapter == null)) {
mPagerAdapter.notifyDataSetChanged();
}

3 - Ich habe die getItemPosition () in mPagerAdapter überschrieben und POSITION_NONE zurückgeben lassen.

 @Override
   public int getItemPosition(Object object) {
     return POSITION_NONE;
    }

wirkt wie charmant

20
Ziad Gholmish

Ich bin auf dieses Problem gestoßen und habe es heute endlich gelöst. Ich schreibe auf, was ich gelernt habe, und hoffe, dass es für jemanden hilfreich ist, der neu in Android ViewPager ist und wie ich aktualisiere. Ich verwende FragmentStatePagerAdapter in API Level 17 und habe derzeit nur 2 Fragmente. Ich denke es muss etwas nicht korrekt sein, bitte korrigieren Sie mich, danke .enter image description here

  1. Serialisierte Daten müssen in den Speicher geladen werden. Dies kann mit CursorLoader/AsyncTask/Thread erfolgen. Ob es automatisch geladen wird, hängt von Ihrem Code ab. Wenn Sie ein CursorLoader verwenden, wird es automatisch geladen, da ein registrierter Datenbeobachter vorhanden ist.

  2. Nachdem Sie viewpager.setAdapter(pageradapter) aufgerufen haben, wird die getCount() des Adapters ständig aufgerufen, um Fragmente zu erstellen. Wenn Daten geladen werden, kann getCount() 0 zurückgeben, sodass Sie keine Dummy-Fragmente erstellen müssen, wenn keine Daten angezeigt werden.

  3. Nachdem die Daten geladen wurden, erstellt der Adapter keine Fragmente automatisch, da getCount() noch 0 ist. Daher können wir die tatsächlich geladene Datennummer so einstellen, dass sie von getCount() zurückgegeben wird, und dann notifyDataSetChanged() des Adapters aufrufen. ViewPager beginnt mit der Erstellung von Fragmenten (nur die ersten 2 Fragmente) anhand der Daten im Speicher. Es wird gemacht, bevor notifyDataSetChanged() zurückgegeben wird. Dann hat ViewPager die richtigen Fragmente, die Sie brauchen.

  4. Wenn die Daten in der Datenbank und im Speicher beide aktualisiert werden (Durchschreiben) oder nur Daten im Speicher aktualisiert werden (Zurückschreiben) oder nur Daten in der Datenbank aktualisiert werden. In den letzten beiden Fällen, wenn Daten nicht automatisch aus der Datenbank in den Speicher geladen werden (wie oben erwähnt) . Der ViewPager- und der Pager-Adapter verarbeiten nur Daten im Speicher.

  5. Wenn also Daten im Speicher aktualisiert werden, müssen wir nur die notifyDataSetChanged() des Adapters aufrufen. Da das Fragment bereits erstellt wurde, wird onItemPosition() des Adapters aufgerufen, bevor notifyDataSetChanged() zurückgegeben wird. In getItemPosition() muss nichts getan werden. Dann werden die Daten aktualisiert.

14
oscarthecat

Versuchen Sie destroyDrawingCache() auf ViewPager nach notifyDataSetChanged() in Ihrem Code.

12
czaku

Nach stundenlangem Frust, während Sie alle oben genannten Lösungen ausprobierten, um dieses Problem zu überwinden, und auch viele Lösungen zu ähnlichen Fragen, wie this , this und this , die alle mit mir fehlgeschlagen sind, um dieses Problem zu lösen und die ViewPager machen, um die alte Fragment zu zerstören und die pager mit der neuen Fragments zu füllen. Ich habe das Problem wie folgt gelöst:

1) Lasse die ViewPager-Klasse FragmentPagerAdapter wie folgt erweitern:

 public class myPagerAdapter extends FragmentPagerAdapter {

2) Erstellen Sie ein Element für die ViewPager, in der die title und die fragment wie folgt gespeichert werden:

public class PagerItem {
private String mTitle;
private Fragment mFragment;


public PagerItem(String mTitle, Fragment mFragment) {
    this.mTitle = mTitle;
    this.mFragment = mFragment;
}
public String getTitle() {
    return mTitle;
}
public Fragment getFragment() {
    return mFragment;
}
public void setTitle(String mTitle) {
    this.mTitle = mTitle;
}

public void setFragment(Fragment mFragment) {
    this.mFragment = mFragment;
}

}

3) Der Konstruktor der ViewPager muss meine FragmentManager-Instanz nehmen, um ihn in meiner class wie folgt zu speichern:

private FragmentManager mFragmentManager;
private ArrayList<PagerItem> mPagerItems;

public MyPagerAdapter(FragmentManager fragmentManager, ArrayList<PagerItem> pagerItems) {
    super(fragmentManager);
    mFragmentManager = fragmentManager;
    mPagerItems = pagerItems;
}

4) Erstellen Sie eine Methode zum Zurücksetzen der adapter-Daten mit den neuen Daten, indem Sie alle vorherigen fragment aus der fragmentManager selbst direkt löschen, um die adapter so zu setzen, dass die neue fragment wie folgt neu gesetzt wird:

public void setPagerItems(ArrayList<PagerItem> pagerItems) {
    if (mPagerItems != null)
        for (int i = 0; i < mPagerItems.size(); i++) {
            mFragmentManager.beginTransaction().remove(mPagerItems.get(i).getFragment()).commit();
        }
    mPagerItems = pagerItems;
}

5) Initialisieren Sie den Adapter mit den neuen Daten nicht aus dem Container Activity oder Fragment. Legen Sie die neuen Daten über die Methode setPagerItems mit den neuen Daten wie folgt fest:

ArrayList<PagerItem> pagerItems = new ArrayList<PagerItem>();
    pagerItems.add(new PagerItem("Fragment1", new MyFragment1()));
    pagerItems.add(new PagerItem("Fragment2", new MyFragment2()));

    mPagerAdapter.setPagerItems(pagerItems);
    mPagerAdapter.notifyDataSetChanged();

Ich hoffe, es hilft.

10
Sami Eltamawy

Aus irgendeinem Grund funktionierte keine der Antworten für mich. Daher musste ich die restoreState-Methode überschreiben, ohne Super in meinem fragmentStatePagerAdapter aufzurufen. Code:

private class MyAdapter extends FragmentStatePagerAdapter {

    // [Rest of implementation]

    @Override
    public void restoreState(Parcelable state, ClassLoader loader) {}

}
7
hordurh

Ich habe die von Bill Phillips angebotene Lösung leicht an meine Bedürfnisse angepasst

private class PagerAdapter extends FragmentStatePagerAdapter{
    Bundle oBundle;
    FragmentManager oFragmentManager;
    ArrayList<Fragment> oPooledFragments;

public PagerAdapter(FragmentManager fm) {
    super(fm);
    oFragmentManager=fm;

    }
@Override
public int getItemPosition(Object object) {

    Fragment oFragment=(Fragment)object;
    oPooledFragments=new ArrayList<>(oFragmentManager.getFragments());
    if(oPooledFragments.contains(oFragment))
        return POSITION_NONE;
    else
        return POSITION_UNCHANGED;
    } 
}

so dass getItemPosition()POSITION_NONE nur für diejenigen Fragmente zurückgibt, die sich aktuell in der FragmentManager befinden, wenn getItemPosition aufgerufen wird .. (Beachten Sie, dass diese FragmentStatePager und die damit verbundene ViewPager in einem Fragment enthalten sind, das sich nicht in einer Aktivität befindet.)

3
adwait

Ich hatte ein ähnliches Problem, möchte aber nicht auf die vorhandenen Lösungen vertrauen (hart codierte Tag-Namen usw.), und ich konnte die Lösung von M-WaJeEh nicht für mich zum Laufen bringen. Hier ist meine Lösung:

Ich verweise auf die in getItem erstellten Fragmente in einem Array. Dies funktioniert einwandfrei, solange die Aktivität nicht aufgrund von configurationChange oder fehlendem Speicher oder sonstigem zerstört wird (-> Wenn Sie zur Aktivität zurückkehren, kehren die Fragmente zu ihrem letzten Status zurück, ohne dass 'getItem' erneut aufgerufen wird und das Array daher nicht aktualisiert wird ).

Um dieses Problem zu vermeiden, habe ich instantiateItem (ViewGroup, int) implementiert und mein Array dort wie folgt aktualisiert:

        @Override
    public Object instantiateItem(ViewGroup container, int position) {
        Object o = super.instantiateItem(container, position);
        if(o instanceof FragmentX){
            myFragments[0] = (FragmentX)o;
        }else if(o instanceof FragmentY){
            myFragments[1] = (FragmentY)o;
        }else if(o instanceof FragmentZ){
            myFragments[2] = (FragmentZ)o;
        }
        return o;
    }

Zum einen bin ich froh, dass ich eine Lösung gefunden habe, die für mich funktioniert und sie mit Ihnen teilen wollte, aber ich wollte auch fragen, ob jemand anderes etwas Ähnliches versucht hat und ob es einen Grund gibt, warum ich das nicht tun sollte mach es so Bisher klappt es sehr gut für mich ...

2
jpm

Ich habe dasselbe Problem gelebt und ich habe zu oft gesucht. Jede Antwort in stackoverflow oder über google war keine Lösung für mein Problem. Mein Problem war einfach. Ich habe eine Liste, ich zeige diese Liste mit Viewpager. Wenn ich ein neues Element zum Kopf der Liste hinzufüge und die Viewpager-Notizen aktualisiert habe, wurden Änderungen vorgenommen. Meine endgültige Lösung war sehr einfach, die jeder benutzen kann. Wenn ein neues Element zur Liste hinzugefügt wird und die Liste aktualisiert werden soll. Setzen Sie zuerst den Viewpager-Adapter auf null, erstellen Sie dann den Adapter neu und setzen Sie ihn auf Viewpager.

myVPager.setAdapter(null);
myFragmentAdapter = new MyFragmentAdapter(getSupportFragmentManager(),newList);
myVPager.setAdapter(myFragmentAdapter);

Stellen Sie sicher, dass Ihr Adapter FragmentStatePagerAdapter erweitern muss

1
nebyan

Wenn Sie FragmentStatePagerAdapter verwenden möchten, werfen Sie einen Blick auf https://code.google.com/p/Android/issues/detail?can=2&start=0&num=100&q=&colspec=ID%20Type%20Status%20Owner% 20Summary% 20Stars & groupby = & sort = & id = 37990 . Es gibt Probleme mit FragmentStatePagerAdapter, die Ihren Anwendungsfall möglicherweise nicht stören. 

Link hat auch zu wenige Lösungen. Wenige passen zu Ihrer Anforderung.

1
cgr

Ich verwende EventBus library, um Fragment Inhalte in ViewPager zu aktualisieren. Die Logik ist einfach, genauso wie Dokument von EventBus, wie zu tun ist. Es ist nicht erforderlich, die FragmentPagerAdapter-Instanz zu steuern. Der Code ist hier:

1: Ereignisse definieren

Legen Sie fest, welche Nachricht aktualisiert werden soll. 

public class UpdateCountEvent {
    public final int count;

    public UpdateCountEvent(int count) {
        this.count = count;
    }
}

2. Bereiten Sie die Abonnenten vor

Schreiben Sie den folgenden Code in das Fragment, das aktualisiert werden muss.

@Override
public void onStart() {
    super.onStart();
    EventBus.getDefault().register(this);
}

@Override
public void onStop() {
    EventBus.getDefault().unregister(this);  
    super.onStop();
}

public void onEvent(UpdateCountEvent event) {//get update message
    Toast.makeText(getActivity(), event.count, Toast.LENGTH_SHORT).show();
}

3.Postveranstaltungen

Schreiben Sie den folgenden Code in eine andere Activity oder andere Fragment, die den Parameter aktualisieren muss 

//input update message
EventBus.getDefault().post(new UpdateCountEvent(count));
1
Fantasy Fang

Ich weiß, ich komme zu spät zur Party. Ich habe das Problem behoben, indem ich TabLayout#setupWithViewPager(myViewPager); direkt nach FragmentPagerAdapter#notifyDataSetChanged(); aufrief

0
theapache64

Dies kann für jemanden hilfreich sein - in meinem Fall fragt der View-Pager beim Einfügen einer neuen Seite zweimal nach der Position eines vorhandenen Fragments, fragt jedoch nicht nach der Position des neuen Elements, was zu falschem Verhalten und nicht angezeigten Daten führt.

  1. Kopieren Sie die Quelle für für FragmentStatePagerAdapter (scheint seit Ewigkeiten nicht aktualisiert worden zu sein).

  2. NotifyDataSetChanged () überschreiben

    @Override
    public void notifyDataSetChanged() {
        mFragments.clear();
        super.notifyDataSetChanged();
    }
    
  3. Fügen Sie eine Sanitätsprüfung zu destroyItem () hinzu, um Abstürze zu verhindern:

    if (position < mFragments.size()) {
        mFragments.set(position, null);
    }
    
0
Meanman

Hier ist meine Implementierung mit den Informationen von @Bill PhillipsOne erhält meistens Fragment-Caching, außer wenn sich die Daten geändert haben. Einfach und scheint gut zu funktionieren.

MyFragmentStatePagerAdapter.Java

private boolean mIsUpdating = false;
public void setIsUpdating(boolean mIsUpdating) {
        this.mIsUpdating = mIsUpdating;
    }


@Override
public int getItemPosition(@NonNull Object object) {

    if (mIsUpdating) {
        return POSITION_NONE;
    }
    else {
        return super.getItemPosition(object);
    }
}

MeineAktivität.Java

mAdapter.setIsUpdating(true);
mAdapter.notifyDataSetChanged();
mAdapter.setIsUpdating(false);
0
voam

Ich habe alle obigen Antworten und eine Reihe anderer Beiträge durchgesehen, konnte aber immer noch nichts finden, was für mich funktionierte (mit verschiedenen Fragmenttypen sowie dynamisch hinzufügen und entfernen). Der FWIW-Ansatz ist das, was für mich funktioniert hat (für den Fall, dass jemand anderes die gleichen Probleme hat). 

public class MyFragmentStatePageAdapter extends FragmentStatePagerAdapter {
    private static final String TAB1_TITLE = "Tab 1";
    private static final String TAB2_TITLE = "Tab 2";
    private static final String TAB3_TITLE = "Tab 3";

    private ArrayList<String> titles = new ArrayList<>();
    private Map<Fragment, Integer> fragmentPositions = new HashMap<>();


    public MyFragmentStatePageAdapter(FragmentManager fm) {
        super(fm);
    }


    public void update(boolean showTab1, boolean showTab2, boolean showTab3) {
        titles.clear();

        if (showTab1) {
            titles.add(TAB1_TITLE);
        }
        if (showTab2) {
            titles.add(TAB2_TITLE);
        }
        if (showTab3) {
            titles.add(TAB3_TITLE);
        }
        notifyDataSetChanged();
    }


    @Override
    public int getCount() {
        return titles.size();
    }

    @Override
    public Fragment getItem(int position) {
        Fragment fragment = null;

        String tabName = titles.get(position);
        if (tabName.equals(TAB1_TITLE)) { 
            fragment =  Tab1Fragment.newInstance();
        } else if (tabName.equals(TAB2_TITLE)) {
            fragment =  Tab2Fragment.newInstance();
        } else if (tabName.equals(TAB3_TITLE)) {
            fragment =  Tab3Fragmen.newInstance();
        } 

        ((BaseFragment)fragment).setTitle(tabName);
        fragmentPositions.put(fragment, position);
        return fragment;
    }

    @Override
    public CharSequence getPageTitle(int position) {
        return titles.get(position);
    }

    @Override
    public int getItemPosition(Object item) {
        BaseFragment fragment = (BaseFragment)item;
        String title = fragment.getTitle();
        int position = titles.indexOf(title);

        Integer fragmentPosition = fragmentPositions.get(item);
        if (fragmentPosition != null && position == fragmentPosition) {
            return POSITION_UNCHANGED;
        } else {
            return POSITION_NONE;
        }
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        super.destroyItem(container, position, object);
        fragmentPositions.remove(object);
    }
}
0
John O'Reilly

Verwenden Sie FragmentStatePagerAdapter anstelle von FragmentPagerAdapter Wenn Sie das Fragment auf Indexbasis neu erstellen oder neu laden möchten Wenn Sie beispielsweise ein anderes Fragment als FirstFragment erneut laden möchten, können Sie die Instanz- und Rückgabeposition wie folgt überprüfen

 public int getItemPosition(Object item) {
    if(item instanceof FirstFragment){
       return 0;
    }
    return POSITION_NONE;
 }
0
HemangNirmal

Diese Lösung funktioniert nicht für alle, aber in meinem Fall ist jedes Fragment in meinem ViewPager eine andere Klasse, und es existiert immer nur eine von ihnen. 

Mit dieser Einschränkung ist diese Lösung sicher und sollte in der Produktion sicher verwendet werden können.

private void updateFragment(Item item) {

    List<Fragment> fragments = getSupportFragmentManager().getFragments();
    for (Fragment fragment : fragments) {

        if (fragment instanceof MyItemFragment && fragment.isVisible()) {
            ((MyItemFragment) fragment).update(item);
        }

    }
}

Wenn Sie über mehrere Versionen desselben Fragments verfügen, können Sie mit derselben Strategie Methoden für diese Fragmente aufrufen, um zu bestimmen, ob es sich um das Fragment handelt, das Sie aktualisieren möchten.

0
Kevin Grant

Ich hatte so viele verschiedene Ansätze ausprobiert, keiner hat mein Problem gekonnt. Im Folgenden wird beschrieben, wie ich es mit einer Mischung von Lösungen löse, die Sie alle zur Verfügung stellen. Vielen Dank an alle.

class PagerAdapter extends FragmentPagerAdapter {

    public boolean flag_refresh=false;

    public PagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int page) {
        FragmentsMain f;
        f=new FragmentsMain();
        f.page=page;
        return f;
    }

    @Override
    public int getCount() {
        return 4;
    }

    @Override
    public int getItemPosition(Object item) {
        int page= ((FragmentsMain)item).page;

        if (page == 0 && flag_refresh) {
            flag_refresh=false;
            return POSITION_NONE;
        } else {
            return super.getItemPosition(item);
        }
    }

    @Override
    public void destroyItem(View container, int position, Object object) {

        ((ViewPager) container).removeView((View) object);
    }
}

Ich möchte nur Seite 0 nach onResume () aktualisieren.

 adapter=new PagerAdapter(getSupportFragmentManager());
 pager.setAdapter(adapter);

@Override
protected void onResume() {
    super.onResume();

    if (adapter!=null) {
        adapter.flag_refresh=true;
        adapter.notifyDataSetChanged();
    }
}

In meinem FragmentsMain gibt es eine öffentliche Ganzzahl "Seite", die mir sagen kann, ob es sich um die Seite handelt, die ich aktualisieren möchte.

public class FragmentsMain extends Fragment {

private Cursor cursor;
private static Context context;
public int page=-1;
0
Ted Hsieh