J'ai une activité avec des onglets de balayage en utilisant les onglets ActionBar, basé sur the android developer example.Le chargeur délivre le résultat à un mauvais fragment
Chaque onglet affiche un fragment, et chaque fragment (en fait, un SherlockFragment) charge un type différent de demande d'API distante via un AsyncTaskLoader personnalisé. Le problème est que si vous appuyez sur un onglet pour déplacer 2 onglets/pages alors que le fragment pour l'onglet que vous quittez (l'ancien fragment) est en train de charger un résultat, ce résultat est livré au fragment pour l'onglet que vous déplacer vers (le nouveau fragment). Dans mon cas, cela conduit à une exception ClassCastException, car les résultats attendus sont de types incompatibles.
Dans le code, l'essentiel de la situation est:
Manutention:
public class FooLoader extends AsyncTaskLoader<Foo>
public class BarLoader extends AsyncTaskLoader<Bar>
Fragments:
public class FooFragment extends Fragment implements LoaderManager.LoaderCallbacks<Foo> {
...
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getLoaderManager().initLoader(0, null, this);
}
public Loader<Foo> onCreateLoader(int id, Bundle args) { return new FooLoader(); }
...
}
public class BarFragment extends Fragment implements LoaderManager.LoaderCallbacks<Bar> {
...
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getLoaderManager().initLoader(0, null, this);
}
public Loader<Bar> onCreateLoader(int id, Bundle args) { return new BarLoader(); }
...
}
Le code de gestion de l'onglet est comme dans le the aforementioned example. Il y a un troisième onglet entre les onglets Foo et Bar (appelez-le Baz). Lorsque nous sautons dans l'onglet Foo à l'onglet Barre en appuyant sur l'onglet Barre après FooFragment a appelé sur son initLoader LoaderManager mais avant FooFragment.onLoadFinished est appelé, nous nous retrouvons avec un ClassCastException sur un appel à BarFragment.onLoadFinished:
java.lang.ClassCastException: com.example.Foo cannot be cast to com.example.Bar
at com.example.BarFragment.onLoadFinished(BarFragment.java:1)
at android.support.v4.app.LoaderManagerImpl$LoaderInfo.callOnLoadFinished(LoaderManager.java:427)
at android.support.v4.app.LoaderManagerImpl.initLoader(LoaderManager.java:562)
at com.example.BarFragment.onCreate(BarFragment.java:36)
at android.support.v4.app.Fragment.performCreate(Fragment.java:1437)
...
Pourquoi cela se produit-il et comment peut-on le prévenir? Il semble à partir des journaux de débogage que le même LoaderManager est réutilisé dans le fragment Barre (bien que le fragment Baz ait le sien), mais je ne sais pas pourquoi cela devrait se produire. L'utilisation de différents ID de chargeur dans chaque fragment élimine le crash (ou semble - je ne sais pas vraiment pourquoi) mais je préférerais ne pas le faire. Dans l'un des fragments, je crée des ID dynamiquement et je ne veux pas supposer qu'il n'y aura pas de collision. Aussi, cette solution est bizarre pour moi - les ID du chargeur doivent être locaux pour chaque fragment (sinon, pourquoi est-ce que je peux avoir des chargeurs avec les mêmes ID dans différents fragments dans des circonstances normales?)
en appelant le setOffscreenPageLimit(2)
sur mon ViewPager, afin que la vue Foo ne soit pas supprimée lorsque nous passons à la vue Barre. Mais c'est une solution de contournement, pas une solution générale.
Code complet: J'ai créé un example application demonstrating the error. Il inclut un script monkeyrunner pour forcer l'erreur (bien que cela puisse ne pas fonctionner pour toutes les tailles d'écran).
Pourriez-vous poster le code complet pour l'un des chargeurs s'il vous plaît. – yarian
Essayez de déplacer votre appel à 'initLoader' dans' onActivityCreated' au lieu de 'onCreate'. –
Cela ressemble à résoudre le problème. Merci! – jgiles