Je ne peux pas mettre à jour le contenu de ViewPager.
Quelle est l'utilisation correcte des méthodes instantiateItem () et getItem () dans la classe FragmentPagerAdapter?
J'utilisais uniquement getItem () pour instancier et renvoyer mes fragments:
@Override
public Fragment getItem(int position) {
return new MyFragment(context, paramters);
}
Cela a bien fonctionné. Sauf que je ne peux pas changer le contenu.
J'ai donc trouvé ceci: ViewPager PagerAdapter ne met pas à jour la vue
"Mon approche consiste à utiliser la méthode setTag () pour toute vue instanciée dans la méthode instantiateItem ()"
Maintenant, je veux implémenter instantiateItem () pour le faire. Mais je ne sais pas ce que je dois retourner (le type est Object) et quelle est la relation avec getItem (int position)?
J'ai lu la référence :
public abstract Fragment getItem (int position)
Renvoie le fragment associé à une position spécifiée.
public Object instantiateItem (conteneur ViewGroup, position int)
Créez la page pour la position donnée. L'adaptateur est responsable de l'ajout de la vue au conteneur indiqué ici, mais il doit uniquement s'assurer que cela est fait au moment où il revient de finishUpdate (ViewGroup). Paramètres
container La vue contenant dans laquelle la page sera affichée. position La position de la page à instancier.
Retour
Renvoie un objet représentant la nouvelle page. Cela n'a pas besoin d'être une vue, mais peut être un autre conteneur de la page.
mais je ne comprends toujours pas.
Voici mon code. J'utilise le package de support 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;
}
}
Voici également quelqu'un avec un problème similaire, aucune réponse http://www.mail-archive.com/[email protected]/msg200477.html
Réponses:
Lorsque vous utilisez FragmentPagerAdapter ou FragmentStatePagerAdapter, il est préférable de traiter uniquement
getItem()
et de ne pas toucherinstantiateItem()
du tout. L' interfaceinstantiateItem()
-destroyItem()
-isViewFromObject()
sur PagerAdapter est une interface de niveau inférieur que FragmentPagerAdapter utilise pour implémenter le plus simplegetItem()
interface .Avant d'entrer dans le détail, je dois préciser que
Une version antérieure de cette réponse a fait l'erreur d'utiliser FragmentPagerAdapter pour son exemple - cela ne fonctionnera pas car FragmentPagerAdapter ne détruit jamais un fragment après qu'il a été affiché la première fois.
Je ne recommande pas
setTag()
etfindViewWithTag()
solution de contournement fourni dans le poste que vous avez lié. Comme vous l'avez découvert, utilisersetTag()
etfindViewWithTag()
ne fonctionne pas avec des fragments, donc ce n'est pas une bonne correspondance.La bonne solution est de passer outre
getItemPosition()
. LorsquenotifyDataSetChanged()
est appelé, ViewPager appellegetItemPosition()
tous les éléments de son adaptateur pour voir s'ils doivent être déplacés vers une position différente ou supprimés.Par défaut,
getItemPosition()
renvoiePOSITION_UNCHANGED
, ce qui signifie: "Cet objet est bien là où il se trouve, ne le détruisez pas ou ne le supprimez pas." Le retourPOSITION_NONE
corrige le problème en disant à la place: "Cet objet n'est plus un élément que j'affiche, supprimez-le." Cela a donc pour effet de supprimer et de recréer chaque élément de votre adaptateur.C'est une solution complètement légitime! Ce correctif permet à notifyDataSetChanged de se comporter comme un adaptateur standard sans recyclage de vue. Si vous implémentez ce correctif et que les performances sont satisfaisantes, vous partez pour les courses. Travail accompli.
Si vous avez besoin de meilleures performances, vous pouvez utiliser une
getItemPosition()
implémentation plus sophistiquée . Voici un exemple pour un pager créant des fragments à partir d'une liste de chaînes:Avec cette implémentation, seuls les fragments affichant de nouveaux titres seront affichés. Tous les fragments affichant des titres qui sont encore dans la liste seront à la place déplacés vers leur nouvelle position dans la liste, et les fragments avec des titres qui ne sont plus du tout dans la liste seront détruits.
Que faire si le fragment n'a pas été recréé, mais doit être mis à jour de toute façon? Les mises à jour d'un fragment vivant sont mieux gérées par le fragment lui-même. C'est l'avantage d'avoir un fragment, après tout - c'est son propre contrôleur. Un fragment peut ajouter un écouteur ou un observateur à un autre objet dans
onCreate()
, puis le supprimeronDestroy()
, gérant ainsi les mises à jour lui-même. Vous n'avez pas besoin de mettre tout le code de mise à jour à l'intérieurgetItem()
comme vous le faites dans un adaptateur pour un ListView ou d'autres types AdapterView.Une dernière chose - ce n'est pas parce que FragmentPagerAdapter ne détruit pas un fragment que getItemPosition est complètement inutile dans un FragmentPagerAdapter. Vous pouvez toujours utiliser ce rappel pour réorganiser vos fragments dans le ViewPager. Cependant, il ne les supprimera jamais complètement du FragmentManager.
la source
FragmentStatePagerAdapter
, je peux voir qu'il supprime mon fragment et crée la nouvelle instance. Mais la nouvelle instance reçoit un BundleInstanceState enregistré avec l'état d'un ancien fragment. Comment puis-je détruire complètement le fragment pour que Bundle soit nul lors de sa création?Au lieu de retourner à
POSITION_NONE
partirgetItemPosition()
et causer des loisirs pleine vue, faites ceci:Vos fragments doivent implémenter l'
UpdateableFragment
interface:et l'interface:
Votre classe de données:
la source
Fragment
dynamiquement, jetez un œil: stackoverflow.com/questions/19891828/…d page on refreshes the 1-st page only after swiping pages? thw 2
page 3D est toujours vierge. mercipour ceux qui sont toujours confrontés au même problème que j'ai rencontré auparavant quand j'ai un
ViewPager
avec 7 fragments. la valeur par défaut pour ces fragments pour charger le contenu anglais duAPI
service, mais le problème ici que je veux changer la langue de l'activité des paramètres et après avoir terminé l'activité des paramètres, je veux que l'ViewPager
activité principale rafraîchisse les fragments pour correspondre à la sélection de la langue de l'utilisateur et charge le contenu arabe si l'utilisateur choisit l'arabe ici ce que j'ai fait pour travailler la première fois1- Vous devez utiliser FragmentStatePagerAdapter comme mentionné ci-dessus.
2- sur mainActivity, j'ai remplacé onResume et j'ai fait ce qui suit
3-i a
getItemPosition()
remplacé le dans mPagerAdapter et le faire revenirPOSITION_NONE
.fonctionne comme un charme
la source
J'ai rencontré ce problème et l'ai finalement résolu aujourd'hui, alors j'écris ce que j'ai appris et j'espère qu'il sera utile pour quelqu'un qui est nouveau sur Android
ViewPager
et le mettra à jour comme je le fais. J'utiliseFragmentStatePagerAdapter
en API niveau 17 et n'ai actuellement que 2 fragments. Je pense qu'il doit y avoir quelque chose de pas correct, veuillez me corriger, merci.Les données sérialisées doivent être chargées en mémoire. Cela peut être fait en utilisant un
CursorLoader
/AsyncTask
/Thread
. Le chargement automatique dépend de votre code. Si vous utilisez unCursorLoader
, il est automatiquement chargé car il existe un observateur de données enregistré.Après avoir appelé
viewpager.setAdapter(pageradapter)
, l'adaptateurgetCount()
est constamment appelé pour créer des fragments. Donc, si les données sont en cours de chargement,getCount()
peut retourner 0, vous n'avez donc pas besoin de créer de fragments factices pour aucune donnée affichée.Une fois les données chargées, l'adaptateur
getCount()
ne crée pas de fragments automatiquement car il est toujours égal à 0, nous pouvons donc définir le numéro de données réellement chargé à renvoyergetCount()
, puis appeler l'adaptateurnotifyDataSetChanged()
.ViewPager
commencer à créer des fragments (juste les 2 premiers fragments) par des données en mémoire. C'est fait avant d'notifyDataSetChanged()
être retourné. Ensuite, leViewPager
a les bons fragments dont vous avez besoin.Si les données dans la base de données et la mémoire sont toutes les deux mises à jour (écriture continue), ou seulement les données en mémoire sont mises à jour (réécriture), ou seules les données dans la base de données sont mises à jour. Dans les deux derniers cas, si les données ne sont pas automatiquement chargées de la base de données dans la mémoire (comme mentionné ci-dessus). L'
ViewPager
adaptateur pager et traite uniquement les données en mémoire.Ainsi, lorsque les données en mémoire sont mises à jour, il nous suffit d'appeler l'adaptateur
notifyDataSetChanged()
. Puisque le fragment est déjà créé, l'adaptateuronItemPosition()
sera appelé avant lesnotifyDataSetChanged()
retours. Rien à fairegetItemPosition()
. Ensuite, les données sont mises à jour.la source
notifyDataSetChanged()
puis de mettre à jour automatiquement, car le fragment (avec graphique) que j'utilise se rafraîchira. si ce n'est pas le cas, comme un fragment statique, jeonItemPositon()
POSITION_NONE
Essayez
destroyDrawingCache()
ViewPager aprèsnotifyDataSetChanged()
dans votre code.la source
Fragments
mon téléavertisseur. Alors merci!Après des heures de frustration en essayant toutes les solutions ci-dessus pour surmonter ce problème et en essayant également de nombreuses solutions sur d'autres questions similaires comme celle-ci , ceci et cela qui ont échoué avec moi pour résoudre ce problème et pour faire
ViewPager
détruire l'ancienFragment
et remplir lepager
avec le nouveau parFragment
. J'ai résolu le problème comme suit:1) Faites en sorte que la
ViewPager
classe s'étendeFragmentPagerAdapter
comme suit:2) Créez un article pour le
ViewPager
qui stocke letitle
et lefragment
suivant:3) Faites en
ViewPager
sorte que le constructeur de la prise monFragmentManager
instance le stocke dans monclass
comme suit:4) Créez une méthode pour réinitialiser les
adapter
données avec les nouvelles données en supprimant directement toutes les précédentesfragment
de lafragmentManager
même afinadapter
de définir à nouveau les nouvellesfragment
de la nouvelle liste comme suit:5) À partir du conteneur
Activity
ouFragment
ne réinitialisez pas l'adaptateur avec les nouvelles données. Définissez les nouvelles données via la méthodesetPagerItems
avec les nouvelles données comme suit:J'espère que ça aide.
la source
Pour une raison quelconque, aucune des réponses n'a fonctionné pour moi, j'ai donc dû remplacer la méthode restoreState sans appeler super dans mon fragmentStatePagerAdapter. Code:
la source
J'ai légèrement modifié la solution proposée par Bill Phillips pour l'adapter à mes besoins
de sorte que le
getItemPosition()
retournePOSITION_NONE
uniquement pour les fragments qui sont actuellement dans leFragmentManager
quandgetItemPosition
est appelé. (Notez que celaFragmentStatePager
et les élémentsViewPager
associés sont contenus dans un fragment qui n'est pas dans une activité)la source
J'ai eu un problème similaire, mais je ne veux pas me fier aux solutions existantes (noms de balises codées en dur, etc.) et je n'ai pas pu faire fonctionner la solution de M-WaJeEh pour moi. Voici ma solution:
Je garde des références aux fragments créés dans getItem dans un tableau. Cela fonctionne bien tant que l'activité n'est pas détruite en raison de configurationChange ou d'un manque de mémoire ou autre (-> en revenant à l'activité, les fragments reviennent à leur dernier état sans que 'getItem' soit appelé à nouveau et donc sans mettre à jour le tableau ).
Pour éviter ce problème, j'ai implémenté instantiateItem (ViewGroup, int) et y mettre à jour mon tableau, comme ceci:
Donc, d'une part, je suis heureux d'avoir trouvé une solution qui fonctionne pour moi et que je voulais la partager avec vous, mais je voulais aussi demander si quelqu'un d'autre a essayé quelque chose de similaire et s'il y a une raison pour laquelle je ne devrais pas fais comme ça? Jusqu'à présent, cela fonctionne très bien pour moi ...
la source
myFragments
danspublic void destroyItem(ViewGroup container, int position, Object object)
si bien que vous ne prenez pas une référence fragement rassis.J'utilise EventBus bibliothèque pour mettre à jour le
Fragment
contenu enViewPager
. La logique est simple, tout comme le document d'EventBus comment faire . Il n'est pas nécessaire de contrôler l'FragmentPagerAdapter
instance. Le code est ici:1: Définir les événements
Définissez le message à mettre à jour.
2. préparer les abonnés
Écrivez ci-dessous le code dans le fragment dont la mise à jour est nécessaire.
3.Post événements
Écrivez ci-dessous le code dans un autre
Activity
ou un autreFragment
qui doit mettre à jour le paramètrela source
Si vous souhaitez utiliser FragmentStatePagerAdapter, veuillez consulter 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 . Il existe des problèmes avec FragmentStatePagerAdapter qui peuvent ou non perturber votre cas d'utilisation.
De plus, link a aussi peu de solutions ... peu peuvent convenir à vos besoins.
la source
J'ai vécu le même problème et j'ai cherché trop de fois. Toute réponse donnée dans stackoverflow ou via google n'était pas une solution à mon problème. Mon problème était facile. J'ai une liste, je montre cette liste avec viewpager. Lorsque j'ajoute un nouvel élément en tête de la liste et que j'actualise le viseur, rien n'a changé. Ma solution finale était très simple à utiliser. Lorsqu'un nouvel élément est ajouté à la liste et que vous souhaitez actualiser la liste. Définissez d'abord l'adaptateur de viewpager sur null, puis recréez l'adaptateur et définissez i sur viewpager.
Assurez-vous que votre adaptateur doit étendre FragmentStatePagerAdapter
la source
Voici mon implémentation qui intègre les informations de @Bill Phillips One obtient la mise en cache des fragments la plupart du temps, sauf lorsque les données ont changé. Simple et semble bien fonctionner.
MyFragmentStatePagerAdapter.java
MyActivity.java
la source
J'avais essayé tellement d'approches différentes, aucune n'a vraiment soulevé mon problème. Voici comment je le résous avec un mélange de solutions fournies par vous tous. Merci tout le monde.
Je veux seulement rafraîchir la page 0 après onResume ().
Dans mon FragmentsMain, il y a une "page" d'entier public, qui peut me dire si c'est la page que je veux rafraîchir.
la source
Je sais que je suis en retard pour le Parti. J'ai résolu le problème en appelant
TabLayout#setupWithViewPager(myViewPager);
juste aprèsFragmentPagerAdapter#notifyDataSetChanged();
la source
Cette solution ne fonctionnera pas pour tout le monde, mais dans mon cas, chaque fragment de mon ViewPager est une classe différente, et un seul d'entre eux existe à la fois.
Avec cette contrainte, cette solution est sûre et doit être sûre à utiliser en production.
Si vous disposez de plusieurs versions du même fragment, vous pouvez utiliser cette même stratégie pour appeler des méthodes sur ces fragments afin de déterminer s'il s'agit du fragment que vous souhaitez mettre à jour.
la source
Cela pourrait être utile à quelqu'un - dans mon cas, lors de l'insertion d'une nouvelle page, le pager de vue demandait la position d'un fragment existant deux fois, mais ne demandait pas la position du nouvel élément, provoquant un comportement incorrect et des données ne s'affichant pas.
Copiez la source de FragmentStatePagerAdapter (semble ne pas avoir été mis à jour depuis longtemps).
Remplacez notifyDataSetChanged ()
Ajoutez une vérification d'intégrité à destroyItem () pour éviter les plantages:
la source
J'ai parcouru toutes les réponses ci-dessus et un certain nombre d'autres messages, mais je n'ai toujours pas trouvé quelque chose qui fonctionnait pour moi (avec différents types de fragments ainsi que l'ajout et la suppression dynamiques d'onglets). L'approche FWIW suivante est ce qui a fonctionné pour moi (au cas où quelqu'un d'autre aurait les mêmes problèmes).
la source
Utilisez FragmentStatePagerAdapter au lieu de FragmentPagerAdapter si vous souhaitez recréer ou recharger le fragment sur la base de l'index Par exemple, si vous souhaitez recharger un fragment autre que FirstFragment, vous pouvez vérifier l'instance et renvoyer la position comme ceci
la source
Vous devez modifier l'élément mFragments d'instantiateItem getItemPosition.
Basé sur AndroidX FragmentStatePagerAdapter.java, car
mFragments
la position des éléments de ne change pas lors de l'appel à notifyDataSetChanged ().La source: https://github.com/cuichanghao/infivt/blob/master/library/src/main/java/cc/cuichanghao/library/FragmentStatePagerChangeableAdapter.java
Exemple: https://github.com/cuichanghao/infivt/blob/master/app/src/main/java/cc/cuichanghao/infivt/MainActivityChangeablePager.kt
Vous pouvez exécuter ce projet pour confirmer le fonctionnement. https://github.com/cuichanghao/infivt
la source