Otto

Otto_Disc

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 à Otto !

 

Otto fonctionne de la manière suivante, si nous voulons envoyer un message de la classe A vers la classe B :

  1. B s’enregistre en tant que receveur auprès d’Otto
  2. A envoie le message à Otto
  3. Otto le transmet à B

Importer Otto

Comme toute librairie, il suffit de l’inclure dans le fichier build.gradle de votre application

build.gradle

compile 'com.squareup:otto:1.3.8'

Créer un Bus

Otto demande de créer un Bus, partagé et visible avec tous les receveurs.
Le plus simple est de déclarer un singleton :

public class MyBus{

   private static Bus bus = new Bus();

   public static Bus getBus(){
        return bus;
   }

}

Déclarer un événement

Première étape pour utiliser Otto : créer nos évènements, les messages qui vont être envoyés via notre Bus. 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 :

MyBus.getBus().post(new PleaseRefreshEvent());

Vous voyez qu’il suffit de lui passer un new PleaseRefreshEvent()

Recevoir un évènement

S’enregistrer auprès d’Otto

Penser à enregistrer l’objet destination en temps que receveur auprès d’Otto, en prenant en compte le cycle de vie de l’activité ou du fragment.
Dans le onStart() on s’enregistre, puis on n’oublie pas de se désinscrire lors du onStop().

public class MyFragment extends Fragment{

    @Override
    public void onStart() {
        super.onStart();
        MyBus.getBus().register(this);
    }
    @Override
    public void onStop() {
        super.onStop();
        MyBus.getBus().unregister(this);
    }

}

Recevoir un événement

Il suffit maintenant d’ajouter une annotation @Subscribe devant notre fonction réceptrice, en n’oubliant pas de lui fournir en paramètre notre event : void mafonction(NOM_EVENT event)

public class MyFragment extends Fragment{

    @Override
    public void onStart() {
        super.onStart();
        MyBus.getBus().register(this);
    }
    @Override
    public void onStop() {
        super.onStop();
        MyBus.getBus().unregister(this);
    }

    @Subscribe
    public void refresh(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) {
                MyBus.getBus().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();
        MyBus.getBus().register(this);
    }

    @Override
    public void onStop() {
        super.onStop();
        MyBus.getBus().unregister(this);
    }

    //This object can receive a PleaseRefreshEvent
    @Subscribe
    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 :

MyBus.getBus().post(new PleaseRefreshEvent("toto"));

Et utiliser les paramètres depuis le onEvent :

@Subscribe
public void refresh(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

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *