撰寫回應式應用程式
維護回應式 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,導致應用程式當機。 我們需要在背景線程上計算我們的值,但在 GUI 線程上執行更新,這會使用 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");
}
}
此程式代碼如預期般運作。 一旦計算完成,此 GUI 會保持回應並正確更新。
請注意,這項技術不只是用於計算昂貴的值。 它可用於可在背景中完成的任何長時間執行工作,例如 Web 服務呼叫或下載因特網數據。