在Android中表示一种消息处理机制或者叫消息处理方法,用来循环处理应用程序主线程各类消息,好比UI的更新,按键、触摸消息事件等。android
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-9app
案例1:sendMenssage方法更新UI界面ide
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对消息进行处理oop
案例2: postDelayed更新UIpost
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处理。
(1) 都是把消息放到消息队列等待执行,前者放的是一个runnable对象,后者是一个message对象;
(2) 前者最终仍是会转化成sendMessage,只不过最终的处理方式不同,前者会执行runnable的run方法;后者能够被安排到线程中执行。
(3) 二者本质没有区别,均可以更新UI,区别在因而否易于维护等。
HandlerThread继承了Thread,是一个包含有looper的线程类。正常状况下,除了主线程,工做线程是没有looper的,可是为了像主线程那样也能循环处理消息,Android也自定义一个包含looper的工做线程——HandlerThread类。
啊啊啊啊啊啊啊啊西吧太菜了,源码看不懂