zoukankan      html  css  js  c++  java
  • Android的Handler机制的一些理解

    Handler是什么

    在Android中表示一种消息处理机制或者叫消息处理方法,用来循环处理应用程序主线程各种消息,比如UI的更新,按键、触摸消息事件等。

    为什么Android要用Handler机制

    Android应用程序启动时,系统会创建一个主线程,负责与UI组件(widget、view)进行交互,比如控制UI界面界面显示、更新等;分发事件给UI界面处理,比如按键事件、触摸事件、屏幕绘图事件等,因此,Android主线程也称为UI线程。
    由此可知,UI线程只能处理一些简单的、短暂的操作,如果要执行繁重的任务或者耗时很长的操作,比如访问网络、数据库、下载等,这种单线程模型会导致线程运行性能大大降低,甚至阻塞UI线程,如果被阻塞超过5秒,系统会提示应用程序无相应对话框,缩写为ANR,导致退出整个应用程序或者短暂杀死应用程序。

    除此之外,单线程模型的UI主线程也是不安全的,会造成不可确定的结果。线程不安全简单理解为:多线程访问资源时,有可能出现多个线程先后更改数据造成数据不一致。比如,A工作线程(也称为子线程)访问某个公共UI资源,B工作线程在某个时候也访问了该公共资源,当B线程正访问时,公共资源的属性已经被A改变了,这样B得到的结果不是所需要的的,造成了数据不一致的混乱情况。
    线程安全简单理解为:当一个线程访问功能资源时,对该资源进程了保护,比如加了锁机制,当前线程在没有访问结束释放锁之前,其他线程只能等待直到释放锁才能访问,这样的线程就是安全的。

    基于以上原因,Android的单线程模型必须遵守两个规则:
    1.  不要阻塞UI线程;
    2.  不要在UI线程之外访问UI组件,即不能在子线程访问UI组件,只能在UI线程访问。

    因此,Android系统将大部分耗时、繁重任务交给子线程完成,不会在主线程中完成,解决了第一个难题;同时,Android只允许主线程更新UI界面,子线程处理后的结果无法和主线程交互,即无法直接访问主线程,这就要用到Handler机制来解决此问题。基于Handler机制,在子线程先获得Handler对象,该对象将数据发送到主线程消息队列,主线程通过Loop循环获取消息交给Handler处理。

    案例用法

    下面两个案例都实现一个定时器,每隔一秒显示数字0-9

    案例1:sendMenssage方法更新UI界面

     1 package com.example.testhandler;
     2  
     3 import android.app.Activity;
     4 import android.os.Bundle;
     5 import android.os.Handler;
     6 import android.os.Message;
     7 import android.view.View;
     8 import android.view.View.OnClickListener;
     9 import android.widget.Button;
    10 import android.widget.TextView;
    11  
    12 public class TestHandlerActivity extends Activity {
    13  
    14     protected static final String TAG = "TestHandlerActivity";
    15     private Button sendButton;
    16     private TextView displayText;
    17  
    18     Handler mHandler = new Handler() {
    19  
    20         @Override
    21         public void handleMessage(Message msg) {
    22             // TODO Auto-generated method stub
    23             if (msg.what == 99) {
    24                 int i = msg.getData().getInt("displayKey");
    25                 displayText.setText(i + "");
    26             }
    27             super.handleMessage(msg);
    28         }
    29  
    30     };
    31     private Button exitButton;
    32  
    33     @Override
    34     protected void onCreate(Bundle savedInstanceState) {
    35         super.onCreate(savedInstanceState);
    36         setContentView(R.layout.activity_main);
    37         initViews();
    38     }
    39  
    40     private void initViews() {
    41  
    42         displayText = (TextView) findViewById(R.id.display_text);
    43         sendButton = (Button) findViewById(R.id.send_button);
    44         sendButton.setOnClickListener(buttonOnClickListener);
    45         exitButton = (Button) findViewById(R.id.exit_button);
    46         exitButton.setOnClickListener(buttonOnClickListener);
    47     }
    48  
    49     OnClickListener buttonOnClickListener = new OnClickListener() {
    50  
    51         @Override
    52         public void onClick(View v) {
    53             // TODO Auto-generated method stub
    54             if (v.getId() == R.id.send_button) {
    55                 new Thread(new WorkRunnable()).start();
    56             } else if (v.getId() == R.id.exit_button) {
    57                 finish();
    58             }
    59         }
    60  
    61     };
    62  
    63     class WorkRunnable implements Runnable {
    64         @Override
    65         public void run() {
    66             // TODO Auto-generated method stub
    67             int i = 0;
    68             while (i < 10) {
    69                 Message msg = mHandler.obtainMessage(99);
    70                 Bundle bundle = new Bundle();
    71                 bundle.putInt("displayKey", i);
    72                 msg.setData(bundle);
    73                 mHandler.sendMessage(msg);
    74                 try {
    75                     Thread.sleep(1000);
    76                 } catch (InterruptedException e) {
    77                     // TODO Auto-generated catch block
    78                     e.printStackTrace();
    79                 }
    80                 i++;
    81             }
    82         }
    83     }
    84  
    85     @Override
    86     protected void onDestroy() {
    87         // TODO Auto-generated method stub
    88         if (mHandler != null) {
    89             if (mHandler.hasMessages(99)) {
    90                 mHandler.removeMessages(99);
    91             }
    92             mHandler = null;
    93         }
    94         super.onDestroy();
    95     }
    96 }

    WorkRunnable的run方法中进行了耗时操作,要把结果反馈给UI,需要Handler发送消息给UI线程,在Handler的handleMessage对消息进行处理

    案例2: postDelayed更新UI

     1 package com.example.postdelaydemo;
     2  
     3 import android.app.Activity;
     4 import android.os.Bundle;
     5 import android.os.Handler;
     6 import android.util.Log;
     7 import android.view.View;
     8 import android.view.View.OnClickListener;
     9 import android.widget.Button;
    10 import android.widget.TextView;
    11  
    12 public class PostDelayActivity extends Activity {
    13     protected static final String TAG = "PostDelayActivity";
    14     private Button sendButton;
    15     private TextView displayText;
    16     private Button exitButton;
    17     Handler mHandler = new Handler();
    18  
    19     @Override
    20     protected void onCreate(Bundle savedInstanceState) {
    21         super.onCreate(savedInstanceState);
    22         setContentView(R.layout.activity_main);
    23         initViews();
    24     }
    25  
    26     private void initViews() {
    27         displayText = (TextView) findViewById(R.id.display_text);
    28         sendButton = (Button) findViewById(R.id.send_button);
    29         sendButton.setOnClickListener(buttonOnClickListener);
    30         exitButton = (Button) findViewById(R.id.exit_button);
    31         exitButton.setOnClickListener(buttonOnClickListener);
    32     }
    33  
    34     OnClickListener buttonOnClickListener = new OnClickListener() {
    35         @Override
    36         public void onClick(View v) {
    37             // TODO Auto-generated method stub
    38             if (v.getId() == R.id.send_button) {
    39                 mHandler.postDelayed(new PostDelayRunnable(), 1000);
    40             } else if (v.getId() == R.id.exit_button) {
    41                 finish();
    42             }
    43         }
    44     };
    45  
    46     class PostDelayRunnable implements Runnable {
    47         int i = 0;
    48  
    49         @Override
    50         public void run() {
    51             // TODO Auto-generated method stub
    52             if (i >= 10) {
    53                 mHandler.removeCallbacks(this);
    54             } else {
    55                 displayText.setText(getResources().getString(
    56                         R.string.display_label)
    57                         + i);
    58                 mHandler.postDelayed(this, 1000);
    59             }
    60             i++;
    61         }
    62     }
    63  
    64     @Override
    65     protected void onDestroy() {
    66         // TODO Auto-generated method stub
    67         if (mHandler != null) {
    68             mHandler = null;
    69         }
    70         super.onDestroy();
    71     }
    72 }

    postDelayed方法把runnable对象作为消息放到队列中等待执行,run方法中就是具体执行过程。

    msg.target是Handler的一个对象引用,handler对象发送消息暂存到消息队列,Looper取出消息分发给相应的handler处理。

    Handler.post(new Runnable())和sendmessage(msg)区别

    (1)  都是把消息放到消息队列等待执行,前者放的是一个runnable对象,后者是一个message对象;
    (2)  前者最终还是会转化成sendMessage,只不过最终的处理方式不一样,前者会执行runnable的run方法;后者可以被安排到线程中执行。

    (3)  两者本质没有区别,都可以更新UI,区别在于是否易于维护等。

    HandlerThread是什么

    HandlerThread继承了Thread,是一个包含有looper的线程类。正常情况下,除了主线程,工作线程是没有looper的,但是为了像主线程那样也能循环处理消息,Android也自定义一个包含looper的工作线程——HandlerThread类。

    啊啊啊啊啊啊啊啊西吧太菜了,源码看不懂

  • 相关阅读:
    #include <functional>
    3.3内联函数
    如何查看内存占用和运行速度
    属性和方法的动态绑定和限制
    __slots__节约空间
    函数进阶之一等对象
    python继承之super
    python的方法VSjava方法
    python面向对象基础(三)内置方法 __xx__
    python面向对象基础(二)反射
  • 原文地址:https://www.cnblogs.com/tero/p/5304118.html
Copyright © 2011-2022 走看看