• Android--多线程之Handler


     

    前言

      Android的消息传递机制是另外一种形式的“事件处理”,这种机制主要是为了解决Android应用中多线程的问题,在Android中不允许Activity新启动的线程访问该Activity里的UI组件,这样会导致新启动的线程无法改变UI组件的属性值。但实际开发中,很多地方需要在工作线程中改变UI组件的属性值,比如下载网络图片、动画等等。本篇博客主要介绍Handler是如何发送与处理线程上传递来的消息,并讲解Message的几种传递数据的方式,最后均会以小Demo来演示。

    Handler

      Handler,它直接继承自Object,一个Handler允许发送和处理Message或者Runnable对象,并且会关联到主线程的MessageQueue中。每个Handler具有一个单独的线程,并且关联到一个消息队列的线程,就是说一个Handler有一个固有的消息队列。当实例化一个Handler的时候,它就承载在一个线程和消息队列的线程,这个Handler可以把Message或Runnable压入到消息队列,并且从消息队列中取出Message或Runnable,进而操作它们。

      Handler主要有两个作用:

    • 在工作线程中发送消息。
    • 在UI线程中获取、处理消息。

      上面介绍到Handler可以把一个Message对象或者Runnable对象压入到消息队列中,进而在UI线程中获取Message或者执行Runnable对象,所以Handler把压入消息队列有两大体系,Post和sendMessage:

    • Post:Post允许把一个Runnable对象入队到消息队列中。它的方法有:post(Runnable)、postAtTime(Runnable,long)、postDelayed(Runnable,long)。
    • sendMessage:sendMessage允许把一个包含消息数据的Message对象压入到消息队列中。它的方法有:sendEmptyMessage(int)、sendMessage(Message)、sendMessageAtTime(Message,long)、sendMessageDelayed(Message,long)。

      从上面的各种方法可以看出,不管是post还是sendMessage都具有多种方法,它们可以设定Runnable对象和Message对象被入队到消息队列中,是立即执行还是延迟执行。

      

    Post

      对于Handler的Post方式来说,它会传递一个Runnable对象到消息队列中,在这个Runnable对象中,重写run()方法。一般在这个run()方法中写入需要在UI线程上的操作。

      在Handler中,关于Post方式的方法有:

    • boolean post(Runnable r):把一个Runnable入队到消息队列中,UI线程从消息队列中取出这个对象后,立即执行。
    • boolean postAtTime(Runnable r,long uptimeMillis):把一个Runnable入队到消息队列中,UI线程从消息队列中取出这个对象后,在特定的时间执行。
    • boolean postDelayed(Runnable r,long delayMillis):把一个Runnable入队到消息队列中,UI线程从消息队列中取出这个对象后,延迟delayMills秒执行
    • void removeCallbacks(Runnable r):从消息队列中移除一个Runnable对象。

       下面通过一个Demo,讲解如何通过Handler的post方式在新启动的线程中修改UI组件的属性:

    复制代码
     1 package com.bgxt.datatimepickerdemo;
     2 
     3 import android.app.Activity;
     4 import android.os.Bundle;
     5 import android.os.Handler;
     6 import android.view.View;
     7 import android.widget.Button;
     8 import android.widget.TextView;
     9 
    10 public class HandlerPostActivity1 extends Activity {
    11     private Button btnMes1,btnMes2;
    12     private TextView tvMessage;
    13     // 声明一个Handler对象
    14     private static Handler handler=new Handler();
    15     
    16     @Override
    17     protected void onCreate(Bundle savedInstanceState) {
    18         super.onCreate(savedInstanceState);
    19         setContentView(R.layout.message_activity);        
    20         
    21         btnMes1=(Button)findViewById(R.id.btnMes1);
    22         btnMes2=(Button)findViewById(R.id.btnMes2);
    23         tvMessage=(TextView)findViewById(R.id.tvMessage);
    24         btnMes1.setOnClickListener(new View.OnClickListener() {
    25             
    26             @Override
    27             public void onClick(View v) {
    28                 // 新启动一个子线程
    29                 new Thread(new Runnable() {                    
    30                     @Override
    31                     public void run() {
    32                         // tvMessage.setText("...");
    33                         // 以上操作会报错,无法再子线程中访问UI组件,UI组件的属性必须在UI线程中访问
    34                         // 使用post方式修改UI组件tvMessage的Text属性
    35                         handler.post(new Runnable() {                    
    36                             @Override
    37                             public void run() {
    38                                 tvMessage.setText("使用Handler.post在工作线程中发送一段执行到消息队列中,在主线程中执行。");                        
    39                             }
    40                         });                                
    41                     }
    42                 }).start();
    43             }
    44         });
    45         
    46         btnMes2.setOnClickListener(new View.OnClickListener() {
    47             
    48             @Override
    49             public void onClick(View v) {
    50                 new Thread(new Runnable() {                    
    51                     @Override
    52                     public void run() {
    53                         // 使用postDelayed方式修改UI组件tvMessage的Text属性值
    54                         // 并且延迟3S执行
    55                         handler.postDelayed(new Runnable() {
    56                             
    57                             @Override
    58                             public void run() {
    59                                 tvMessage.setText("使用Handler.postDelayed在工作线程中发送一段执行到消息队列中,在主线程中延迟3S执行。");    
    60                                 
    61                             }
    62                         }, 3000);                        
    63                     }
    64                 }).start();
    65                 
    66             }
    67         });
    68     }
    69 }
    复制代码
  • 相关阅读:
    解析Javascript事件冒泡机制(转)
    JavaScript事件处理的三种方式(转)
    javaScript中"=="和"==="运算符的区别
    博客
    基础知识巩固二
    基础知识巩固
    知识小结(浮点数问题)
    关于电脑桌面图标消失并且右键无法点击的情况
    JS随笔(二)
    关于JS学习笔记
  • 原文地址:https://www.cnblogs.com/banxia123-ha/p/7101090.html
Copyright © 2020-2023  润新知