EventBus
Envie de passer une information entre différents fragments ? Ou simplement indiquer depuis une activité à un fragment qu’il doit se rafraichir ? Oubliez les anciennes méthodes un peu bancales, faites place à EventBus !
EventBus fonctionne de la manière suivante, si nous voulons envoyer un message de la classe A vers la classe B :
- B s’enregistre en tant que receveur auprès d’EventBus
- A envoie le message à EventBus
- EventBus le transmet à B
Importer EventBus
Comme toute librairie, il suffit de l’inclure dans le fichier build.gradle de votre application
build.gradle
compile 'de.greenrobot:eventbus:2.4.0'
Déclarer un événement
Première étape pour utiliser EventBus : créer nos évènements, les messages qui vont être envoyés par EventBus. Imaginons le cas suivant : je veux demander à un Fragment d’afficher « Refresh », et ce depuis mon Activité. Je vais créer un objet PleaseRefreshEvent (on peux lui donner le nom que l’on veux).
PleaseRefreshEvent.java
public class PleaseRefreshEvent{ }
Lancer un événement
Depuis n’importe quel endroit de votre code, vous pouvez transmettre un événement :
EventBus.getDefault().post(new PleaseRefreshEvent());
Vous voyez qu’il suffit de lui passer un new PleaseRefreshEvent()
Recevoir un évènement
S’enregistrer auprès d’EventBus
Penser à enregistrer l’objet destination en temps que receveur auprès d’EventBus, en prenant en compte le cycle de vie de l’activité ou du fragment.
Dans le onStart() on s’enregistre auprès d’EventBus, puis on n’oublie pas de se désinscrire lors du onStop().
public class MyFragment extends Fragment{ @Override public void onStart() { super.onStart(); EventBus.getDefault().register(this); } @Override public void onStop() { super.onStop(); EventBus.getDefault().unregister(this); } }
Recevoir un événement
Il suffit maintenant d’ajouter une fonction void onEvent(NOM_EVENT event) à notre classe, ce qui donne pour un PleaseRefreshEvent
public class MyFragment extends Fragment{ @Override public void onStart() { super.onStart(); EventBus.getDefault().register(this); } @Override public void onStop() { super.onStop(); EventBus.getDefault().unregister(this); } public void onEvent(PleaseRefreshEvent event){ //votre action } }
Exemple complet
MainActivity.java
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button button = (Button) findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { EventBus.getDefault().post(new PleaseRefreshEvent()); } }); } }
layout/activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <Button android:id="@+id/button" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/please_refresh"/> <fragment android:id="@+id/myFragment" android:name="com.tutosandroidfrance.eventbussample.fragment.MyFragment" android:layout_width="match_parent" android:layout_height="match_parent"/> </LinearLayout>
J’ai choisi ici d’ajouter le fragment directement depuis le layout, afin de le rendre transparent depuis le code Java de l’activité.
L’activité contiendra donc à son lancement le fragment MyFragment.
MyFragment.java
public class MyFragment extends Fragment{ TextView textView; @Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment,container,false); } @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); textView = (TextView) view.findViewById(R.id.text); } @Override public void onStart() { super.onStart(); EventBus.getDefault().register(this); } @Override public void onStop() { super.onStop(); EventBus.getDefault().unregister(this); } //This object can receive a PleaseRefreshEvent public void onEvent(PleaseRefreshEvent event){ textView.setText(getString(R.string.refresh)); } }
layout/fragment.xml
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/text" android:text="@string/question" android:layout_gravity="center"/> </FrameLayout>
Voici le résultat, au click du bouton, le contenu du Fragment se met à jour :
Extras
Petite astuce, il est possible de transmettre des données avec notre évènement, pour cela il suffit d’ajouter des propriétés à notre événement :
public class PleaseRefreshEvent{ private String myString; public PleaseRefreshEvent(String myString){ this.myString = myString; } public String getMyString(){ return myString; } }
Vous pouvez ensuite l’envoyer de la manière suivante :
EventBus.getDefault().post(new PleaseRefreshEvent("toto"));
Et utiliser les paramètres depuis le onEvent :
public void onEvent(PleaseRefreshEvent event){ textView.setText(event.getMyString()); }
Vous n’avez plus aucune excuse pour ne pas utiliser cette fabuleuse librairie 🙂
Les sources de ce tuto sont disponibles sur gihub
Merci infiniment, il y a aussi Otto de square-up, mais je pense que EventBus est de loin le meilleure ! 😀
J’ai fait un tuto sur Otto aussi, il sortira bientôt 😉