现在的位置: 首页 > 综合 > 正文

Android中的handler

2014年02月16日 ⁄ 综合 ⁄ 共 2413字 ⁄ 字号 评论关闭

这几天经常在开发android的时候需要用到多线程,其实很多地方是必须用到的,比如进度条的更新,动画的显示,等等,你必须开一个线程来单独管理这些界面元素的变化,因为你不能因为更新个进度条把主线程给阻塞了,这不科学。而且别人都说了,永远不要阻塞主线程,一切从用户的角度出发。那么今天我在写多线程的时候,需要更新进度条的progress,那么就需要在run方法中不断的屈更新progress这个值,然后再对这个进度条setprogress,怎么半呢?我的进度条是一个局部变量,于是我自己定义了一个内部类,把这个进度条对象当作构造函数的参数传入线程类中,然后再在run方法中更新这个progress。然后我直接new了一个对象,然后start了

接下来运行,便抛出了异常,Only the original thread that created a view hierarchy can touch its views

为什么呢?

当每个应用程序apk第一次启动时,Android会同时启动一个对应的主线程(Main Thread)
主线程负责处理与UI相关的事件,如:用户的按键事件,用户接触屏幕的事件以及屏幕绘图事件,
并把相关的事件分发到对应的组件进行处理,所以主线程通常又被叫做UI线程。在android内核剖析这本书中就介绍过这个线程类,其实就是ActivityThread这个类。书中这么讲到:

应用程序启动时,从ActivityThread开始,

ActivityThread从main方法开始执行,调用一个方法创建MessageQueue,

然后创建一个ActivityThread对象,在初始化代码中会创建一个Handler和一个Binder,binder负责接受调用,然后通过handler将调用发送给消息队列,

主线程会异步地从消息队列中取出消息并执行相应的动作。

但是在开发Android应用时必须遵守单线程模型的原则: 
      Android UI操作并不是线程安全的并且这些操作必须在UI线程中执行,如果在非UI线程中直接操作UI线程,
      会抛出android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that 
      created a view hierarchy can touch its views,这与普通的java程序不同。

由于UI线程负责事件的监听和绘图,因此,必须保证UI线程能够随时响应用户的需求,
UI线程里的操作应该向中断事件那样短小,费时的操作(如网络连接)需要另开线程,
否则,如果UI线程超过5s没有响应用户请求,会弹出对话框提醒用户终止应用程序(ANP)

如果在新开的线程中需要对UI进行设定,就可能违反单线程模型,
因此android采用一种的Message Queue机制保证线程间通信

 Message Queue是一个消息队列,用来存放通过Handler发送的消息。
Android在第一启动程序时会默认会为UI thread创建一个关联的消息队列,
可以通过Looper.myQueue()得到当前线程的消息队列,用来管理程序的一些上层组件,
activities,broadcast receivers 等,你可以在自己的子线程中创建Handler与UI thread通讯

Handler会向message queue通过两种方法发送消息:send或post。
这两种消息都会插在message queue队尾并按先进先出执行,
但通过这两种方法发送的消息执行的方式略有不同:
 1)通过send发送的是一个message对象, 会被handler的 handleMessage()函数处理;
 2)而通过post方法发送的是一个runnable对象,则会自己执行。

Handler的官方描述:


A Handler allows you to send and process Message and
Runnable objects associated with a thread's MessageQueue.
Each Handler instance is associated with a single thread and that thread's message queue. When you create a new Handler, it is bound to the thread / message queue of the thread that is creating it -- from that point on, it will deliver messages and runnables
to that message queue and execute them as they come out of the message queue


.Handler的使用场合:

 

1、 to schedule messages and runnables to be
executed as some point in the future;

      安排messages和runnables在将来的某个时间点执行。

2、 to enqueue an action to be performed on a
different thread than your own.

      将action入队以备在一个不同的线程中执行。即可以实现线程间通信。比如当你创建子线程时,你可以再你的子线程中拿到父线程中创建的Handler对象,就可以通过该对象向父线程的消息队列发送消息了。由于Android要求在UI线程中更新界面,因此,可以通过该方法在其它线程中更新界面。


通过Handler更新UI实例:

步骤:

1、创建Handler对象(此处创建于主线程中便于更新UI)。

2、构建Runnable对象,在Runnable中更新界面。

3、在子线程的run方法中向UI线程post,runnable对象来更新UI。

抱歉!评论已关闭.