zoukankan      html  css  js  c++  java
  • 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)
                    {
    
                    }
                }
            }
        } 
    }

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

  • 相关阅读:
    [译] iOS 11.4.1 Beta:全新的USB限制模式
    [杂] 无人机取证的一些研究
    [杂] 将高版本iTunes备份恢复到低版本iOS设备中
    [手机取证] Apple Watch取证初探
    [手机取证] 绕过屏幕锁定启用调试模式-For Android 4.4.2
    [手机取证] “神器”IP-BOX的一些问题
    [杂] BOSE QC15维修小记
    iOS 8潜在的取证问题
    [Fraud] China UnionPay defrauded in Macau money laundering scandal
    [DFNews] Fire-Eye与Fox IT联合推出Cryptolocker解锁网站
  • 原文地址:https://www.cnblogs.com/swjian/p/8652816.html
Copyright © 2011-2022 走看看