Schreiben von reaktionsfähigen AnwendungenWriting Responsive Applications

Einer der Schlüssel zum Verwalten einer reaktionsfähigen GUI ist das Ausführen von Aufgaben mit langer Ausführungszeit in einem Hintergrund Thread, damit die GUI nicht blockiert wird.One of the keys to maintaining a responsive GUI is to do long-running tasks on a background thread so the GUI doesn't get blocked. Nehmen wir an, wir möchten einen Wert berechnen, der dem Benutzer angezeigt wird, aber dieser Wert benötigt 5 Sekunden für die Berechnung:Let's say we want to calculate a value to display to the user, but that value takes 5 seconds to calculate:

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";
    }
}

Dies funktioniert, aber die Anwendung bleibt 5 Sekunden lang hängen, während der Wert berechnet wird.This will work, but the application will "hang" for 5 seconds while the value is calculated. Während dieser Zeit antwortet die APP nicht auf eine Benutzerinteraktion.During this time, the app will not respond to any user interaction. Um dies zu umgehen, möchten wir unsere Berechnungen in einem Hintergrund Thread durchführen:To get around this, we want to do our calculations on a background thread:

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";
    }
}

Nun berechnen wir den Wert in einem Hintergrund Thread, damit unsere GUI während der Berechnung reaktionsfähig bleibt.Now we calculate the value on a background thread so our GUI stays responsive during the calculation. Wenn die Berechnung jedoch abgeschlossen ist, stürzt unsere App ab und verlässt Sie im Protokoll:However, when the calculation is done, our app crashes, leaving this in the log:

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 ()

Dies liegt daran, dass Sie die GUI über den GUI-Thread aktualisieren müssen.This is because you must update the GUI from the GUI thread. Der Code aktualisiert die GUI aus dem Thread Pool-Thread, wodurch die APP abstürzt.Our code updates the GUI from the ThreadPool thread, causing the app to crash. Wir müssen unseren Wert im Hintergrund Thread berechnen, aber dann das Update auf dem GUI-Thread durchführen, der mit " Activity. runonuithread" behandelt wird:We need to calculate our value on the background thread, but then do our update on the GUI thread, which is handled with 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");
    }
}

Dieser Code funktioniert erwartungsgemäß.This code works as expected. Diese GUI bleibt reaktionsfähig und wird nach dem Berechnen der Berechnung ordnungsgemäß aktualisiert.This GUI stays responsive and gets properly updated once the calculation is comple.

Beachten Sie, dass diese Technik nicht nur zum Berechnen eines teuren Werts verwendet wird.Note this technique isn't just used for calculating an expensive value. Sie kann für alle Aufgaben mit langer Ausführungszeit verwendet werden, die im Hintergrund ausgeführt werden können, wie z. b. ein Webdienst oder das Herunterladen von Internetdaten.It can be used for any long-running task that can be done in the background, like a web service call or downloading internet data.