J'ai 5 fragments dans ViewPager
utilisés pour remplir un objet métier avec plusieurs champs étape par étape, à chaque étape, certains de ces champs seront définis. J'ai lu de nombreux articles sur la communication entre fragments, mais je ne me sens pas à l'aise comme les autres le préfèrent. Après avoir réfléchi à COMMENT puis-je faire cela dans mon cas, je commence enfin à penser à utiliser un objet modèle singleton auquel tous les fragments peuvent facilement accéder à ses champs et les remplir en étapes spécifiques.
En tant que nouvel utilisateur d'Android, je souhaite que les experts parlent de l'utilisation de singleton au lieu de transmettre des données entre des fragments tels qu'une interface implémentée (il semble que ce soit si compliqué et difficile à maintenir). Tout conseil sera utile.
Bien que l’approche singleton semble facile à mettre en œuvre et à comprendre, c’est la meilleure façon de réaliser ce dont vous avez besoin. Une des raisons est que votre objet modèle, ou comme vous l'appelez, objet métier, vit en dehors du contexte de votre activité, ce qui peut créer des bogues difficiles à trouver. Par exemple. dans le cas où plusieurs instances de votre classe d'activité sont créées par le système et que les deux gardent une référence à votre singleton. Voyez comment vous perdez la trace de vos objets?
Ce que je ferais c'est
Parcelable
vous le détesterez au début, mais une fois que vous vous y habituerez, il deviendra le meilleur ami de votre modèle.parcelable
, vous pouvez désormais le transmettre facilement entre fragments, activités et même l'enregistrer dans les préférences partagées. Il est important de noter ici que lorsque vous passez votre parcelable
entre un fragment ou une activité, c’est comme si vous passiez par valeur, c’est-à-dire chaque fois qu'une nouvelle instance est créée. Définissez l'argument de votre fragment ou, s'il est déjà instancié, obtenez les arguments et ajoutez votre modèle. voici un exemple: si un fragment n’est pas encore actif:
Bundle args = new Bundle();
args.putParcable("businessObject", yourBusinessObjectThatIsParcable);
yourFragment.setArguments(args);
Sinon: yourFragment.getArguments().putParcelable("businessObject", yourBusinessObjectThatIsParcable);
Dans votre fragment, peut-être dans la méthode onCreateView, obtenez votre objet modèle comme ceci: MyParcableObject mpo = (MyParcableObject)getArguments().getParcelable("businessObject")
et utilisez-le pour définir les données de votre choix.
Lorsque vous avez terminé de modifier votre objet lors d'un clic sur un bouton ou dans la méthode onPause, mettez à jour les arguments de votre fragment de la même manière, _getArguments().putParcelable("businessObject", mpo);
dans votre dernière page ou dernier fragment, vous pouvez transmettre votre objet à votre activité, ici comment procéder
Même si cela semble fastidieux, vous devez vous y habituer en tant que développeur Android. Vous obtenez beaucoup plus de contrôle lorsque votre modèle implémente parcelable
.
Une autre façon de faire ce dont vous avez besoin est/ Modèle de délégation mais il est principalement utilisé pour les rappels, même si vous pouvez également transmettre des objets.
Je ne recommanderais pas un singleton global. Il y a deux principales raisons:
onSaveInstanceState()
et à le restaurer dans onCreate()
.Tous les fragments du ViewPager peuvent obtenir une référence à l'activité parent via un appel à getActivity()
. Ou si votre ViewPager est dans un fragment, tous les fragments peuvent accéder au fragment parent via un appel à getParentFragment()
. Vous pouvez ensuite transtyper le résultat dans la classe appropriée (ou mieux encore, l'interface) et effectuer des appels de méthode pour transmettre des données en arrière. Gardez une trace des données de votre entreprise dans l'activité/le fragment parent. De cette façon, vous n'avez pas besoin d'un singleton global
Par exemple,
public class MyParentFragment extends Fragment {
private String mPageOneData;
private int mPageTwoData;
private List<Date> mPageThreeData;
public void setPageOneData(String data) {
mPageOneData = data;
}
...
}
public class PageOneFragment extends Fragment {
private void sendDataToParent(String data) {
Fragment f = getParentFragment();
if (f != null && f instanceof MyParentFragment) {
MyParentFragment parent = (MyParentFragment) f;
f.setPageOneData(data);
}
}
}
vous pouvez enregistrer vos données dans l'événement onSaveInstanceState () de l'activité au cas où votre processus passerait à l'arrière-plan. Vous pouvez restaurer vos données dans l'événement onCreate () en utilisant Bundle et getExtras ().
vous pouvez sauvegarder vos données dans la classe d’application et les données seront toujours là au cas où votre processus passerait à l’arrière-plan.
je préfère la première option parce que vous ne voulez pas créer de désordre dans la classe d’application avec toutes les données provenant de différentes activités et fragments. J'espère pouvoir vous aider :)
Avez-vous acheté EventBus ?
Je ne suis pas sûr que ce soit la meilleure approche, surtout quand votre question est trop large, mais ce sera cool avec seulement 5 fragments.
J'espère que ça aide
Avant de choisir une option, n'oubliez pas que l'utilisateur peut naviguer ou ouvrir n'importe quelle autre application afin que vous perdiez vos données.
Vous pouvez utiliser onSaveInstanceState
mais il sera en quelque sorte difficile à maintenir (comme vous l'avez dit, vous êtes nouveau dans Android). Vous pouvez aller avec singleton en utilisant
SharefPreference
(de préférence) - Si vous souhaitez utiliser des valeurs uniques.Dans les deux cas, vous allez créer un objet singleton et accéder à ses propriétés dans vos fragments.
Je suppose que dans votre activité principale, il y a une ViewPager
, et FragmentOne
sera l'un des fragments à l'intérieur du pageur de vue. Ici, MainActivity communique avec FragmentOne pour actualiser son adaptateur. L'espoir est clair.
Dans votre MainActivity, ajoutez cette interface:
public interface Updateable {
public void update();
}
Implémentez cette interface dans un fragment qui doit être mis à jour et écrivez le code pour notifier l'adaptateur dans la méthode update
:
public class FragmentOne extends Fragment implements MainActivity.Updateable {
...
@Override
public void update() {
// YOUR CODE TO UPDATE HERE, FOR EXAMPLE, HERE I'M UPDATING THE ADAPTER
if ( adapter != null ) {
adapter.notifyDataSetChanged();
} else {
Log.d("LOG_TAG", "null");
}
}
...
}
Appelez la méthode update
à partir de MainActivity lorsque le fragment est chargé en premier. Vous pouvez faire ceci en remplaçant la méthode getItemPosition
dans votre PagerAdapter
, comme ceci:
@Override
public int getItemPosition(Object object) {
if ( object != null && object instanceof FragmentOne ) {
FragmentOne f = (FragmentOne) object;
f.update();
}
return super.getItemPosition(object);
}
Enfin, vous devez appeler notifyDataSetChanged () de votre adaptateur viewPager. Cela forcera l'adaptateur de votre viewpager à appeler la méthode getItemPosition.
mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
int previousState;
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
if (previousState == ViewPager.SCROLL_STATE_SETTLING && state == ViewPager.SCROLL_STATE_IDLE) {
if ( viewPagerAdapter.getItem(viewpager.getCurrentItem()) instanceof Pictures ) {
Log.d("LOG_TAG", "New Position=" + viewpager.getCurrentItem());
viewPagerAdapter.notifyDataSetChanged();
}
}
previousState = state;
}
});