• Xamarin.Android 使用线程无法更改页面文本问题


    前言:

      刚接触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)
                    {
    
                    }
                }
            }
        } 
    }

    这样问题就完美的解决了。

  • 相关阅读:
    level trigger 与 edge trigger 的区别
    使用ifstream时碰到的一个小问题
    转一篇 sed one line
    select(poll)效率,与异步网络IO,AIO, libevent, epoll
    类的成员函数指针的使用
    awk 的OFS使用 小 tips
    一句话打通所有机器,小脚本
    usleep sleep函数会重置clock 的返回值
    qstore 的 chunk重构小记
    判断质数的方法
  • 原文地址:https://www.cnblogs.com/swjian/p/8652816.html
Copyright © 2020-2023  润新知