编写响应式应用程序
维护响应式 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 服务调用或下载 Internet 数据。