Quelle est la portée d'un LoaderManager?
Question
Lors de l'identification chargeurs dans votre LoaderManager, vous utilisez ids uniques. Je demande comment ces ids uniques doivent être.
Est-ce que chaque activité et fragment ont sa propre LoaderManager? fragments Utilisez-le LoaderManager de l'activité, ils sont attachés à? Est-il un seul LoaderManager que l'application possède?
Les points bonus si vous pouvez me dire comment il est possible de changer ce qui LoaderManager que vous utilisez. Si je veux que chaque fragment dans mon activité à utiliser la même LoaderManager (certains d'entre eux tirent les mêmes données et le partage de chargeurs serait bien), est-ce possible?
La solution
Je suis actuellement le portage de ma demande au package de compatibilité Android (principalement pour CursorLoader et fragments). J'essaie actuellement de partager un CursorLoader entre deux fragments d'épargner une requête à mon ContentProvider. Bienvenue dans mon monde! ;)
Un simple cas d'utilisation:
- DummyActivity étend FragmentActivity / Log.d (. Constants.LOGTAG, "DummyActivity.onCreate" + getSupportLoaderManager () toString ());
- DataFragment étend met en œuvre Fragment LoaderManager.LoaderCallbacks / Log.d (. Constants.LOGTAG, "DataFragment.onCreate" + getLoaderManager () toString ());
- ReportFragment étend met en œuvre Fragment LoaderManager.LoaderCallbacks / Log.d (. Constants.LOGTAG, "ReportFragment.onCreate" + getLoaderManager () toString ());
DummyActivity instancie le DataFragment et instancie plus tard, le ReportFragment. La sortie logcat adresses de spectacles pour chaque LoaderManager. En première conclusion, chaque fragment semble avoir une bonne LoaderManager ...
Je vais poursuivre et mise à jour si je peux répondre à votre (notre;)) question. Si vous avez fait des progrès, s'il vous plaît partager vos connaissances précieuses.
Mise à jour:
Mon hypothèse est que le chargeur ids ne sont associés à une portée locale d'un LoaderManager pour un fragment spécifique pour permettre plusieurs chargeurs locaux à associer avec le fragment (de sorte que vous pouvez retourner un chargeur différent dans onCreateLoader basé sur l'id int arg et les appels initLoader).
Jusqu'à présent, je réussi à "réutilisation" un chargeur (ou non ...):
-. D'abord, j'ai permis LoaderManager débogage avec getSupportLoaderManager().enableDebugLogging(true);
dans la méthode onCreate
de DummyActivity
-. Je l'ai appelé getActivity().getSupportLoaderManager().initLoader(78, null, this);
des méthodes de onCreate
des deux DataFragment et ReportFragment
-. DataFragment expose le CursorLoader créé par la méthode onCreateLoader
par l'intermédiaire d'un setter sur un membre privé mCursorLoader
-. La onCreateLoader
de ReportFragment renvoie le DataFragment CursorLoader (après récupération de l'Fragment avec findFragmentByTag
)
Le filtre (et légèrement obscurci) Sortie logcat:
DummyApp D DummyActivity.onCreate
DummyApp D DataFragment.newInstance
DummyApp D ReportFragment.newInstance
DummyApp D DataFragment.onCreate
LoaderManager V initLoader in LoaderManager{405a19d0 in SpecificAction{4059ee98}}: args=null
DummyApp D DataFragment.onCreateLoader
LoaderManager V Created new loader LoaderInfo{405a2298 #78 : CursorLoader{405a22e0}}
DummyApp D DataFragment.onCreate
DummyApp D DataFragment.onActivityCreated
DummyApp D ReportFragment.onCreate
LoaderManager V initLoader in LoaderManager{405a19d0 in DummyActivity{4059ee98}}: args=null
LoaderManager V Re-using existing loader LoaderInfo{405a2298 #78 : CursorLoader{405a22e0}}
DummyApp D SpecificActionReportFragment.onCreate
DummyApp D SpecificActionReportFragment.onActivityCreated
LoaderManager V Starting in LoaderManager{405a19d0 in DummyActivity{4059ee98}}
LoaderManager V Starting: LoaderInfo{405a2298 #78 : CursorLoader{405a22e0}}
DummyProvider D query called
DummyProvider D […]
DummyProvider D [end of query]
LoaderManager V onLoadComplete: LoaderInfo{405a2298 #78 : CursorLoader{405a22e0}}
LoaderManager V onLoadFinished in CursorLoader{405a22e0 id=78}: CursorWrapperInner{405afb20}
DummyApp D ReportFragment.onLoadFinished
DummyApp D ReportFragment.displayActionReport
DummyApp D DummyActivity.setReportViewsVisibility
DummyApp D ReportFragment.setSaveReportImageViewVisibility
Les deux fragments sont ajoutés à partir de la méthode onCreate
de DummyActivity (différent du cas d'utilisation décrit, mais qui ne change rien à la question que nous travaillons). Malheureusement, le chargeur est réassigné au dernier fragment appelant (ici ReportFragment) ... et DataFragment.onLoadFinished est jamais appelé. En conséquence, le ReportFragment semble bon mais le DataFragment est pas à jour depuis la mise à jour est appelée à partir du onLoadFinished
de cette classe.
Je suppose qu'il ya un appel désinscription qui sous-tend alors un appel sur le registre CursorLoader.
A suivre ...
Autres conseils
Oui. Il a travaillé pour moi. J'ai 3 différents fragments dans un tiroir où la navigation les mêmes données sont renseignées dans différentes listviews. (Tous les fragments sont une partie de l'activité SAME).
Mon AsyncTaskLoader:
public class MyTaskLoader extends AsyncTaskLoader<HashMap<String, Integer>> {
public MyTaskLoader(Context context) {
super(context);
}
@Override
public HashMap<String, Integer> loadInBackground() {
...
return hashMap;
}
...
}
Utilisez le même chargeur Id dans tous les fragments.
Fragment1:
public class Fragment1 extends BaseFragment implements LoaderManager.LoaderCallbacks<HashMap<String, Integer>> {
@Override
public void onCreate(Bundle savedInstanceState) {
//initialize adapter
getActivity().getSupportLoaderManager().initLoader(0, null, this);
}
@Override
public Loader<HashMap<String, Integer>> onCreateLoader(int arg0, Bundle arg1) {
// TODO Auto-generated method stub
return new MyTaskLoader(getActivity());
}
@Override
public void onLoadFinished(Loader<HashMap<String, Integer>> arg0,
HashMap<String, Integer> data) {
// TODO Auto-generated method stub
listAdapter.setData(data.keySet());
}
@Override
public void onLoaderReset(Loader<HashMap<String, Integer>> arg0) {
// TODO Auto-generated method stub
listAdapter.setData(null);
}
}
Utilisez le même identifiant pour Fragment2:
public class Fragment2 extends BaseFragment implements LoaderManager.LoaderCallbacks<HashMap<String, Integer>> {
@Override
public void onCreate(Bundle savedInstanceState) {
//initialize adapter
getActivity().getSupportLoaderManager().initLoader(0, null, this);
}
@Override
public Loader<HashMap<String, Integer>> onCreateLoader(int arg0, Bundle arg1) {
// TODO Auto-generated method stub
return new MyTaskLoader(getActivity());
}
@Override
public void onLoadFinished(Loader<HashMap<String, Integer>> arg0,
HashMap<String, Integer> data) {
// TODO Auto-generated method stub
listAdapter.setData(data.keySet());
}
@Override
public void onLoaderReset(Loader<HashMap<String, Integer>> arg0) {
// TODO Auto-generated method stub
listAdapter.setData(null);
}
}
L'adaptateur doit être initialisé avant d'initialiser le chargeur. Fonctionne jusqu'à présent. Mais, est-ce la bonne voie? Y at-il une meilleure méthode d'utilisation d'un chargeur commun pour plusieurs fragments?