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)
                    {
    
                    }
                }
            }
        } 
    }

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

  • 相关阅读:
    移动端默认meta标签
    css3 变形(transform)、转换(transition)和动画(animation)
    Java_ToolKit用法
    Java_I/O输入输出_实现当用户输入姓名和密码时,将每一个姓名和密码加在文件中,如果用户输入done,就结束程序。
    Java_I/O输入输出_实现读取文件时出现一个表示读取进度的进度条。可以使用java.swing包提供的输入流类ProgressMonitorInputStream
    Java_Swing程序设计_尝试开发一个登陆窗体,包括用户名、密码以及提交按钮和重置按钮,当用户输入用户名my,密码love时,弹出登陆成功提示对话框。
    Eclipse通过jdbc连接oracle数据库
    Java_I/O输入输出_使用输入输出流读取文件,将一段文字加密后存入文件,然后读取,将加密前与后的文件输出
    asp.net缓存机制
    深入理解abstract class和interface
  • 原文地址:https://www.cnblogs.com/swjian/p/8652816.html
Copyright © 2011-2022 走看看