Credo che FragmentStatePagerAdapter non si comporti correttamente quando si esegue l'override di getItemPosition(Object object)
allo scopo di riordinare le pagine.riordina le pagine in FragmentStatePagerAdapter utilizzando getItemPosition (oggetto Object)
Di seguito è riportato un semplice esempio. Nello stato iniziale, l'ordine delle pagine è {A, B, C}. Alla chiamata toggleState()
, l'ordine delle pagine cambia in {A, C, B}. Ignorando getItemPosition(Object object)
, ci assicuriamo che la pagina corrente visualizzata (A, B o C) non cambi.
public static class TestPagerAdapter extends FragmentStatePagerAdapter {
private boolean mState = true;
public TestPagerAdapter(FragmentManager fragmentManager) {
super(fragmentManager);
}
@Override
public int getCount() {
return 3;
}
private void toggleState() {
mState = !mState;
notifyDataSetChanged();
}
private String getLabel(int position) {
switch (position) {
case 0:
return "A";
case 1:
return mState ? "B" : "C";
default:
return mState ? "C" : "B";
}
}
@Override
public int getItemPosition(Object object) {
String label = ((TestFragment) object).getLabel();
if (label.equals("A")) {
return 0;
} else if (label.equals("B")) {
return mState ? 1 : 2;
} else {
return mState ? 2 : 1;
}
}
@Override
public CharSequence getPageTitle(int position) {
return getLabel(position);
}
@Override
public Fragment getItem(int position) {
return TestFragment.newInstance(getLabel(position));
}
}
Ho riscontrato due comportamenti separati che sembrano errati.
Se chiamo subito
toggleState()
(durante la visualizzazione di pagina A, prima di strisciare a qualsiasi altra pagina), l'applicazione si blocca.java.lang.IndexOutOfBoundsException: Invalid index 2, size is 2 at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:251) at java.util.ArrayList.set(ArrayList.java:477) at android.support.v4.app.FragmentStatePagerAdapter.destroyItem(FragmentStatePagerAdapter.java:136) at android.support.v4.view.ViewPager.populate(ViewPager.java:867) at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:469) at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:441) at android.support.v4.view.ViewPager.dataSetChanged(ViewPager.java:766) at android.support.v4.view.ViewPager$PagerObserver.onChanged(ViewPager.java:2519) at android.database.DataSetObservable.notifyChanged(DataSetObservable.java:37) at android.support.v4.view.PagerAdapter.notifyDataSetChanged(PagerAdapter.java:276) at com.ugglynoodle.test.testfragmentstatepageradapter.MainActivity$TestPagerAdapter.toggleState(MainActivity.java:55) ...
Guardando la fonte di
FragmentStatePagerAdapter
, questo sarebbe stato risolto dalla prima controllando la dimensione delmFragments
(come in linee 113-115) prima di chiamareset()
in linea 136.Se ho magnetica per pagina B, quindi viene chiamato
getItem(2)
, viene creata la pagina C emFragments
ha ora una dimensione pari a 3 (ciò impedirà l'arresto anomalo di cui sopra in un momento). Poi torno alla pagina A, e la pagina C viene distrutta, come dovrebbe essere (dato che è a 2 pagine di distanza, e sto usando il limite predefinito della pagina fuori schermo di 1). Ora chiamotoggleState()
. La pagina B è ora distrutta. Tuttavia, la pagina C NON viene ricreata! Ciò significa che quando passo il dito verso destra, ottengo una pagina vuota.
In primo luogo, sarebbe bello sapere se sono corretto e questi sono in realtà bug o se sto facendo qualcosa di sbagliato. Se sono bug, qualcuno può suggerire una soluzione alternativa (a parte il debug e la ricostruzione della libreria di supporto da solo)? Sicuramente qualcuno deve aver sostituito con successo getItemPosition(Object object)
(a parte impostare tutto su POSITION_NONE
)?
Sto utilizzando la revisione corrente (10) della libreria di supporto.
Ho usato l'implementazione fissa, ma un problema che sto affrontando è NO updation di frammenti prossimo in ViewPager.How posso aggiustarlo? –
Penso che tu sia azzeccato, @UgglyNoodle, volevo solo far notare che se stai bene con i frammenti riordinati distrutti e ricreati, restituisci POSITION_NONE per i frammenti il cui ordine è cambiato e POSTION_UNCHANGED per quei frammenti che non sono cambiati ottiene il risultato desiderato anche senza schiantarsi. –