Écriture d’applications réactives

L’une des clés pour maintenir une interface graphique graphique réactive est d’effectuer des tâches de longue durée sur un thread d’arrière-plan afin que l’interface graphique graphique ne soit pas bloquée. Supposons que nous voulons calculer une valeur à afficher pour l’utilisateur, mais que cette valeur prend 5 secondes pour calculer :

public class ThreadDemo : Activity
{
    TextView textview;

    protected override void OnCreate (Bundle bundle)
    {
        base.OnCreate (bundle);

        // Create a new TextView and set it as our view
        textview = new TextView (this);
        textview.Text = "Working..";

        SetContentView (textview);

        SlowMethod ();
    }

    private void SlowMethod ()
    {
        Thread.Sleep (5000);
        textview.Text = "Method Complete";
    }
}

Cela fonctionnera, mais l’application « se bloque » pendant 5 secondes pendant que la valeur est calculée. Pendant ce temps, l’application ne répond à aucune interaction utilisateur. Pour contourner ce problème, nous voulons effectuer nos calculs sur un thread d’arrière-plan :

public class ThreadDemo : Activity
{
    TextView textview;

    protected override void OnCreate (Bundle bundle)
    {
        base.OnCreate (bundle);

        // Create a new TextView and set it as our view
        textview = new TextView (this);
        textview.Text = "Working..";

        SetContentView (textview);

        ThreadPool.QueueUserWorkItem (o => SlowMethod ());
    }

    private void SlowMethod ()
    {
        Thread.Sleep (5000);
        textview.Text = "Method Complete";
    }
}

Maintenant, nous calculons la valeur sur un thread d’arrière-plan afin que notre interface graphique graphique reste réactive pendant le calcul. Toutefois, lorsque le calcul est effectué, notre application se bloque, laissant ceci dans le journal :

E/mono    (11207): EXCEPTION handling: Android.Util.AndroidRuntimeException: Exception of type 'Android.Util.AndroidRuntimeException' was thrown.
E/mono    (11207):
E/mono    (11207): Unhandled Exception: Android.Util.AndroidRuntimeException: Exception of type 'Android.Util.AndroidRuntimeException' was thrown.
E/mono    (11207):   at Android.Runtime.JNIEnv.CallVoidMethod (IntPtr jobject, IntPtr jmethod, Android.Runtime.JValue[] parms)
E/mono    (11207):   at Android.Widget.TextView.set_Text (IEnumerable`1 value)
E/mono    (11207):   at MonoDroidDebugging.Activity1.SlowMethod ()

Cela est dû au fait que vous devez mettre à jour l’interface graphique graphique à partir du thread d’interface graphique graphique. Notre code met à jour l’interface graphique graphique à partir du thread ThreadPool, ce qui provoque le blocage de l’application. Nous devons calculer notre valeur sur le thread d’arrière-plan, mais ensuite effectuer notre mise à jour sur le thread d’interface graphique graphique, qui est géré avec Activity.RunOnUIThread :

public class ThreadDemo : Activity
{
    TextView textview;

    protected override void OnCreate (Bundle bundle)
    {
        base.OnCreate (bundle);

        // Create a new TextView and set it as our view
        textview = new TextView (this);
        textview.Text = "Working..";

        SetContentView (textview);

        ThreadPool.QueueUserWorkItem (o => SlowMethod ());
    }

    private void SlowMethod ()
    {
        Thread.Sleep (5000);
        RunOnUiThread (() => textview.Text = "Method Complete");
    }
}

Ce code fonctionne comme prévu. Cette interface graphique graphique reste réactive et est correctement mise à jour une fois le calcul effectué.

Notez que cette technique n’est pas utilisée uniquement pour calculer une valeur coûteuse. Il peut être utilisé pour n’importe quelle tâche de longue durée qui peut être effectuée en arrière-plan, comme un appel de service web ou le téléchargement de données Internet.