Написание адаптивных приложений
Одним из ключей поддержания адаптивного графического интерфейса является выполнение длительных задач в фоновом потоке, чтобы графический интерфейс не был заблокирован. Предположим, что мы хотим вычислить значение для отображения пользователю, но это значение занимает 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";
}
}
Теперь мы вычисляем значение в фоновом потоке, чтобы наш графический интерфейс оставался адаптивным во время вычисления. Однако при выполнении вычисления приложение завершает работу, оставляя это в журнале:
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 ()
Это связано с тем, что необходимо обновить графический интерфейс из потока графического интерфейса. Наш код обновляет графический интерфейс из потока ThreadPool, что приводит к сбою приложения. Нам нужно вычислить наше значение в фоновом потоке, но затем выполнить обновление в потоке ГРАФИЧЕСКОго интерфейса, который обрабатывается с помощью 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");
}
}
Этот код работает должным образом. Этот графический интерфейс остается адаптивным и правильно обновляется после выполнения вычисления.
Обратите внимание, что этот метод не просто используется для вычисления дорогого значения. Его можно использовать для любой длительной задачи, которая может выполняться в фоновом режиме, например вызов веб-службы или скачивание интернет-данных.