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
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.
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
}
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
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 .
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.
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.
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.
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.
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.
Versuchen Sie destroyDrawingCache()
auf ViewPager nach notifyDataSetChanged()
in Ihrem Code.
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 Fragment
s 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.
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) {}
}
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.)
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 ...
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
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.
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));
Ich weiß, ich komme zu spät zur Party. Ich habe das Problem behoben, indem ich TabLayout#setupWithViewPager(myViewPager);
direkt nach FragmentPagerAdapter#notifyDataSetChanged();
aufrief
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.
Kopieren Sie die Quelle für für FragmentStatePagerAdapter (scheint seit Ewigkeiten nicht aktualisiert worden zu sein).
NotifyDataSetChanged () überschreiben
@Override
public void notifyDataSetChanged() {
mFragments.clear();
super.notifyDataSetChanged();
}
Fügen Sie eine Sanitätsprüfung zu destroyItem () hinzu, um Abstürze zu verhindern:
if (position < mFragments.size()) {
mFragments.set(position, null);
}
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);
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);
}
}
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;
}
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.
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;