반응형 애플리케이션 작성

반응형 GUI를 기본 키 중 하나는 백그라운드 스레드에서 장기 실행 작업을 수행하여 GUI가 차단되지 않도록 하는 것입니다. 사용자에게 표시할 값을 계산하려고 하지만 해당 값을 계산하는 데 5초가 걸린다고 가정해 보겠습니다.

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

이 작업은 작동하지만 값이 계산되는 동안 애플리케이션은 5초 동안 "중단"됩니다. 이 시간 동안 앱은 사용자 상호 작용에 응답하지 않습니다. 이를 해결하려면 백그라운드 스레드에서 계산을 수행하려고 합니다.

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

이제 GUI가 계산 중에 응답성을 유지할 수 있도록 백그라운드 스레드의 값을 계산합니다. 그러나 계산이 완료되면 앱이 충돌하여 로그에 그대로 둡니다.

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

이는 GUI 스레드에서 GUI를 업데이트해야 하기 때문입니다. 코드는 ThreadPool 스레드에서 GUI를 업데이트하여 앱이 충돌합니다. 백그라운드 스레드에서 값을 계산해야 하지만 Activity.RunOnUIThread처리되는 GUI 스레드에서 업데이트를 수행합니다.

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

이 코드는 예상대로 작동합니다. 이 GUI는 응답성을 유지하고 계산이 완료되면 제대로 업데이트됩니다.

이 기술은 고가의 값을 계산하는 데만 사용되는 것이 아닙니다. 웹 서비스 호출 또는 인터넷 데이터 다운로드와 같이 백그라운드에서 수행할 수 있는 장기 실행 작업에 사용할 수 있습니다.