学习通过Thread+Handler实现非UI线程更新UI组件(转)

 

【Android线程机制】

   出于性能考虑,Android的UI操作并不是线程安全的,这就意味着如果有多个线程并发操作UI组件,可能导致线程安全问题。为了解决这个问题,Android制定了一条简单的规则:只允许UI线程修改Activity里的UI组件

   当一个程序第一次启动时,Android会同时启动一条主线程(Main Thread),主线程主要负责处理与UI相关的事件,如用户的按键事件,用户接触屏幕的事件及屏幕绘图事件,并把相关的事件分发到对应的组件进行处理。所以主线程通常又被叫做UI线程

【Handler类简介】

  Handler类主要作用有两个:

  -->在新启动的线程发送消息

   -->在主线程中获取、处理消息

【原理】

    为了让线程能“适时”地处理新启动的线程所发送的消息,显然只能通过回调的方法来实现---开发者只需要重写Handler类中的处理消息的方法,当新启动的线程发送消息时,消息会发送到与之关联的MessageQueue,而Handler会不断地从MessageQueue中获取并处理消息-这将导致Handler类中的处理消息的方法被回调

 

【Handler类中用于发送和处理消息的方法 】

 

. void handleMessage(Message msg):                                处理消息的方法。该方法通常用于被重写
. final boolean hasMessages(int what):                                检查消息队列中是否包含what属性为指定值的消息
. final boolean hasMessages(int what,Object object) :     检查消息队列中是否包含what属性为指定值 
                                                                                          的消息且object属性为指定对象的消息
. 多个重载的Message obtainMessage():                            获取消息
. sendEmptyMessage(int what):                                         发送空消息
. final boolean sendEmptyMessageDelayed(int what,long delayMills):           指定多少秒后发送空消息
. final boolean sendMessage(Message msg):                                               立即发送消息
. final boolean sendMessageDelayed(Message msg,long delayMills):           指定多少秒后发送消息

 

-----------------------------------------------------------------------------------------------------------------

下面通过一个例子实现Android线程操作机制

eg:通过点击按钮,来实现异步加载csdn的logo

效果图:

【代码】

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

package cn.edu.bzu.asynchronous_processomg;

  

import org.apache.http.HttpResponse;

import org.apache.http.client.HttpClient;

import org.apache.http.client.methods.HttpGet;

import org.apache.http.impl.client.DefaultHttpClient;

  

import android.os.Bundle;

import android.os.Handler;

import android.os.Message;

import android.app.Activity;

import android.graphics.Bitmap;

import android.graphics.BitmapFactory;

import android.view.Menu;

import android.view.View;

import android.view.View.OnClickListener;

import android.widget.Button;

import android.widget.ImageView;

import android.widget.Toast;

  

/**

 * 学习通过Thread+Handler实现非UI线程更新UI组件

 * 学习异步加载的使用

 * @author monster

 *  date:2015-05-28

 *  introduce : Android只允许UI线程修改Activity里的UI组件

 *  Aim:点击按钮读取CSDN网站的LOGO

 */  

public class MainActivity extends Activity {

   private Button mButton;

   private ImageView mImageView; 

     

   private final static int MSG_SUCCESS = 0; //获取图片成功的标识

   private final static int MSG_FAILURE = 1; //获取图片失败的标识

     

   private Thread mThread;

     

   private Handler mHandler=new Handler(){

       public void handleMessage(Message msg){  //此方法在UI线程中运行

           switch(msg.what){

               case MSG_SUCCESS:

                   mImageView.setImageBitmap((Bitmap)msg.obj); //得到obj,并且强制类型转换成Bitmap类型--->>>obj含有图片的信息

                   Toast.makeText(getApplication(), "success", Toast.LENGTH_LONG).show();

                   break;    

               case MSG_FAILURE:

                   Toast.makeText(getApplication(), "error", Toast.LENGTH_LONG).show();

                   break;

           }

       }

         

   };

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        //实例化控件的时候,如果为当前上下文的时候,则不需要写上下文

        mButton=(Button)findViewById(R.id.mButton);

        mImageView=(ImageView)findViewById(R.id.mImageView);

          

        mButton.setOnClickListener(new OnClickListener() {

              

            @Override

            public void onClick(View v) {

                if(mThread==null){

                    mThread=new Thread(runnable);

                    mThread.start();

                }

            }

        });

    }

            Runnable runnable=new Runnable() {

                  

                @Override

                public void run() {

                     //run()在新的线程中运行 

                    HttpClient hc=new DefaultHttpClient();

                    HttpGet hg=new HttpGet("http://csdnimg.cn/www/images/csdnindex_logo.gif"); //csdn 的logo

                    final Bitmap bm;

                    try {

                        HttpResponse hr=hc.execute(hg); // 响应做出的请求

                        bm=BitmapFactory.decodeStream(hr.getEntity().getContent());

                    } catch (Exception e) {

                        mHandler.obtainMessage(MSG_FAILURE).sendToTarget();//获取图片失败

                        return ;

                    }

                    mHandler.obtainMessage(MSG_SUCCESS,bm).sendToTarget();//获取图片成功

                }

            };

  

    @Override

    public boolean onCreateOptionsMenu(Menu menu) {

        getMenuInflater().inflate(R.menu.main, menu);

        return true;

    }

      

}

【总结】

   Handle在代码中为一个主线程,Runnable为一个新线程,新线程中通过请求响应的方法得到网站的logo,然后通过Handle消息传递机制进行传递从网站中读取的图片,这个图片为一个bitmap,是通过把文件流转换成bitmap,然后进行消息传递

 

【链接分享】

   http://blog.csdn.net/mylzc/article/details/6736988

 

【源代码下载地址】

  https://github.com/monsterLin/Asy_Processing

 

 

 

 

http://www.cnblogs.com/boy1025/p/4537856.html

时间: 2024-09-22 22:17:54

学习通过Thread+Handler实现非UI线程更新UI组件(转)的相关文章

OkHttp3几个简单的例子和在子线程更新UI线程的方法

okHttp用于android的http请求.据说很厉害,我们来一起尝尝鲜.但是使用okHttp也会有一些小坑,后面会讲到如何掉进坑里并爬出来. 首先需要了解一点,这里说的UI线程和主线程是一回事儿.就是唯一可以更新UI的线程.这个只是点会在给okHttp填坑的时候用到.而且,这个内容本身在日常的开发中也经常用到,值得好好学一学. okHttp发起同步请求 第一个列子是一个同步请求的例子. private void performSyncHttpRequest() { OkHttpClient

详解Android中OkHttp3的例子和在子线程更新UI线程的方法

okHttp用于android的http请求.据说很厉害,我们来一起尝尝鲜.但是使用okHttp也会有一些小坑,后面会讲到如何掉进坑里并爬出来. 首先需要了解一点,这里说的UI线程和主线程是一回事儿.就是唯一可以更新UI的线程.这个只是点会在给okHttp填坑的时候用到.而且,这个内容本身在日常的开发中也经常用到,值得好好学一学. okHttp发起同步请求 第一个列子是一个同步请求的例子. private void performSyncHttpRequest() { OkHttpClient

android中子线程更新UI的方式

一.为何写作此文 你是不是经常看到很多书籍中说:不能在子线程中操作ui,不然会报错.你是不是也遇到了如下的疑惑(见下面的代码): (Bundle savedInstanceState) { .onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv = (TextView) findViewById(R.id.tv); Thread.currentThread().setName(); LooperThrea

C# 后台线程更新UI控件

/********************************************************************************* * C# 后台线程更新UI控件 * 说明: * C#多线程更新UI控件的方法,每次都要找,记录一下,方便检索. * * 2017-10-23 深圳 南山平山村 曾剑锋 ********************************************************************************/ 一

c# UI线程更新 阻塞问题

问题描述 在一个窗口中有动态显示当前得到时间label还有动态显示当前摄像头的图像,还有一些功能按钮,当我点击功能按钮的时候动态显示的时间还有图像会有卡顿请问有可能避免吗,请教啊!急!!! 解决方案 解决方案二:如果你把工作都在前台线程做,无论如何都会卡,只是有时候卡的时间太短,让你觉得不卡而已.对于这种让界面卡的工作,你应该用一个后台线程(BackgroundWorker)去处理.解决方案三:publicstaticclassControlCrossThreadCalls{publicdele

Android中子线程和UI线程通信详解_Android

Android中子线程和UI线程之间通信的详细解释 1.在多线程编程这块,我们经常要使用Handler,Thread和Runnable这三个类,那么他们之间的关系你是否弄清楚了呢?下面详解一下. 2.首先在开发Android应用时必须遵守单线程模型的原则: Android UI操作并不是线程安全的并且这些操作必须在UI线程中执行. 3.Handler: (1).概念: Handler是沟通Activity 与Thread/runnable的桥梁.而Handler是运行在主UI线程中的,它与子线程

Android开发之子线程操作UI的几种方法_Android

 在Android项目中经常有碰到这样的问题,在子线程中完成耗时操作之后要更新UI,下面就自己经历的一些项目总结一下更新的方法: 在看方法之前需要了解一下Android中的消息机制. 方法1 Activity.runOnUiThread 方法如下: runOnUiThread(new Runnable() { @Override public void run() { tv.setText("Hello"); } }); 这种方法简单易用,如果当前线程是UI线程,那么行动是立即执行.如

ui-关于android子线程操作UI的问题

问题描述 关于android子线程操作UI的问题 看到的所有的资料上都说android的子线程不能操作UI,抱着好奇心我写了下面的程序,竟然运行成功了,不知谁能解释一下这个问题 public class MainActivity extends Activity { Button bt; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setCon

wpf 线程-WPF UI线程问题 急急急急急急急急急急急

问题描述 WPF UI线程问题 急急急急急急急急急急急 已经调用UI线程更新操作位什么还出现这个问题啊? propertyManage1.Dispatcher.Invoke(new Action(delegate { propertyManage1.Children.Add(canvas); })); 调用线程无法访问此对象,因为另一个线程拥有该对象