前言:
刚接触Xamarin.Android不到一个月时间,却被他折磨的不要不要的,随着开发会出现莫名其妙的问题,网上类似Xamarin.Android的文档也不多,于是本片文章是按照Java开发Android的思路写过来的,于是记录下来,希望大家碰到这个问题少走些弯路。
问题描述:
在执行线程内想给TextView赋值发生错误。
错误提示:
Android.Util.AndroidRuntimeException: Only the original thread that created a view hierarchy can touch its views.
问题原因:
原来Android中相关的view和控件不是线程安全的,我们必须单独做处理。这里借此引出Handler的使用。
Handler的机制:
handler机制,在android中提供了一种异步回调机制Handler,使用它,我们可以在完成一个很长时间的任务后做出相应的通知。
Handler的作用:
当我们需要在子线程处理耗时的操作(例如访问网络,数据库的操作),而当耗时的操作完成后,需要更新UI,这就需要使用Handler来处理,因为子线程不能做更新UI的操作。Handler能帮我们很容易的把任务(在子线程处理)切换回它所在的线程。简单理解,Handler就是解决线程和线程之间的通信的。
原有错误代码:
using System;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using System.Threading;
namespace App1
{
[Activity(Label = "App1", MainLauncher = true, Icon = "@drawable/icon")]
public class MainActivity : Activity
{
TextView tv1;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Main);
Button button = FindViewById<Button>(Resource.Id.MyButton);
button.Click += delegate { TestThread(); };
tv1 = FindViewById<TextView>(Resource.Id.textView1);
}
private void TestThread()
{
Boolean loopFlag = true;
Thread th = new Thread(new ThreadStart(delegate
{
int i = 0;
while (loopFlag && i < 5)
{
if (i == 3)
{
tv1.Text = "测试赋值";
loopFlag = false;
}
i++;
}
}));
th.Start();
}
}
}
修改完成后的代码:
using System;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using System.Threading;
namespace App1
{
[Activity(Label = "App1", MainLauncher = true, Icon = "@drawable/icon")]
public class MainActivity : Activity
{
TextView tv1;
Handler hander;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Main);
Button button = FindViewById<Button>(Resource.Id.MyButton);
hander = new UIHand(this);
button.Click += delegate { TestThread(); };
tv1 = FindViewById<TextView>(Resource.Id.textView1);
}
//模拟一个线程,在线程中修改TextView的文本
private void TestThread()
{
Boolean loopFlag = true;
Thread th = new Thread(new ThreadStart(delegate
{
int i = 0;
while (loopFlag && i < 5)
{
if (i == 3)
{
Message ms = new Message();
ms.Obj = "测试赋值" + "@" + "123";
hander.SendMessage(ms); //调用HandleMessage方法
loopFlag = false;
}
i++;
}
}));
th.Start();
}
//创建一个类,继承于Handler
private class UIHand : Handler
{
MainActivity ma;
public UIHand(MainActivity _ma)
{
ma = _ma;
}
//重写HandleMessage方法
public override void HandleMessage(Message msg)
{
try
{
String result = msg.Obj + ""; //相当于ToString();
String[] str = result.Split('@');
ma.tv1.Text = str[0];
}
catch (Exception)
{
}
}
}
}
}
这样问题就完美的解决了。