您的位置:首页 > 移动开发 > Android开发

Android Handle机制浅析

2015-12-21 23:47 316 查看
Android为了安全方面的考虑,是不允许线程对UI线程进行直接操作的。

而如果我们想通过线程对界面进行操作,有如下的几种方法:
在子线程中提供了5中方法来实现与UI线程的交互:

第一种方法:Activity.runUiThread(Runnable)

第二种方法:View.post(Runnable);

第三种方法:View.postDelayed(Runnable);

第四种方法:Handler、Message、Looper

第五种方法:AsyncTask

这里说说Handler机制:

一.基本概念:

1. 消息类:Message类

 android.os.Message的主要功能是进行消息的封装,同时可以指定消息的操作形式

2. 消息通道:Looper

  在使用Handler处理Message时,需要Looper(通道)来完成。在一个Activity中,系统会自动帮用户启动Looper对象,而在一个用户自定义的类中,则需要用户手工调用Looper类中的方法,然后才可以正常启动Looper对象。Looper的字面意思是“循环者”,它被设计用来使一个普通线程变成Looper线程。所谓Looper线程就是循环工作的线程。

3. 消息操作类:Handler类

  Message对象封装了所有的消息,而这些消息的操作需要android.os.Handler类完成。handler起到了处理M消息的作用(只处理由自己发出的消息),它要执行一个任务(sendMessage),并在loop到自己的时候执行该任务(handleMessage),整个过程是异步的。







如图:
Handle的四大核心机制是:Message,Handle,Looper,target
是怎样的一个过程?
        1一个线程可以有多个hander,每个hander都有自己标识的target
2.一个线程只有一个looper(只负责从队列中按顺序循环取出消息)
然后每个handler把looper循环出的消息根据target标识来处理自己的消息。
二.常见问题:
问题1.Handle导致内存泄露及解决方案?
  由target和ThreadLocal解决。
  ThreadLocal是什么?
 JDK 1.2的版本中就提供java.lang.ThreadLocal,ThreadLocal为解决多线程程序的并发问题提供了一种新的思路。使用这个工具类可以很简洁地编写出优美的多线程程序,ThreadLocal并不是一个Thread,而是Thread的局部变量。具体请参照博客:http://lavasoft.blog.51cto.com/62575/51926/
  简单来说:它就是线程真正保存线程自己本地变量的容器。每一个线程都有自己的单独的一个空间,致使不同线程调用同个数据是不会发生混乱。 
问题2:handler为什么阻塞?
  1。在handler队列中,没有handler存在的情况,Looper就不发生阻塞,不会再从

消息队列中获取message

  2。如果handle创建的时间小于message队列中一些message的放入时间。

那么Looper就不会去轮询这些message了,产生阻塞。因为,Looper是先要看handle的脸色后再去轮询消息的。
问题3:内存泄露问题?



如图:如果开启线程向服务器加载图片,但加载不来。每个类里面都存有其他的对象的应用
,这个线程不会销毁,一直请求。这种强引用不会自动中断,就会内存溢出。

解决方案:中断引用

  Handler.removeMessage()

  Handler.romoveCallbacks

问题4:如果handler创建在子线程,如何更新接受到消息后更新ui?
 先看下面方法:

  Looper.myLooper()【当前Activity的线程,不可更新UI】

  Looper.prepare();

  Looper.loop();

new Thread(){//创建一个子线程
public void run() {
Looper.prepare();
Handler hander=new Handler(Looper.myLooper()){
public void dispatchMessage(android.os.Message msg) {

//可以接受到消息,但不能在这个子线程中更新UI
};
};
Looper.loop();
};
}.start();如果找到主线程的Looper就可以了。

Looper.getMainLooper//ActivityThread创建的looper[可以更新UI]
new Thread(){//创建一个子线程
public void run() {
Handler hander=new Handler(Looper.getMainLooper()){
public void dispatchMessage(android.os.Message msg) {

//通过接受的消息,在子线程中更新UI
};
};
};
}.start();原因:这个looper是主Activity初始化时,就创建的,既然是主线程当然可以更新UI。

looper对消息可以对我们自定义的message执行操作,而且还对系统定义消息类型,执行操作。
下篇博客讲下:第五种方法:AsyncTask
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  线程