framework学习(1)——源码的角度分析handler(1)

大前提

Android中更新Ui必须在主线程,在子线程更新Ui会报子线程不能修改UI异常如果任意线程都可以更新UI的话,线程安全问题处理起来会相当麻烦复杂,就会出现页面错乱。所以就规定了Android的是单线程模型,只允许在UI线程更新UI操作。那如果有许多需要耗时的操作都放在UI主线程中执行的话,必然会造成主线程的卡顿,会阻塞掉UI线程,导致手机不再显示或者接受用户新的操作,给用户一种死机的感觉。因此最好的方法是将用户耗时较长的操作放到另一个线程中去,并且用监听者模式来监听操作的完成。
这里handler解决的办法就是去通知主线程而已,所以归根结底,handler就是作为异步交互的桥梁存在的

Handler是什么?

主要用于异步消息的处理:当发出一个消息之后,首先进入一个消息队列,发送消息的函数即刻返回,而另外一个部分在消息队列中逐一将消息取出,然后对消息进行处理,也就是发送消息和接收消息不是同步的处理。 这种机制通常用来处理相对耗时比较长的操作。
简单说Handler就是谷歌的Android的为了开发人员封装的一套更新UI的机制,消息处理机制。就是为了方便开发者人员的。

Handler的几个部分

Mssage:储存信息。
Handler:把Message添加到MssageQueue里,处理Looper发送过来的Message。
Looper:取出MessageQueue的Message,将Message发送到Handler。
MessageQueue:储存Handler发送过来的Message
简单说:
当一个应用启动时,会初始化一个UI线程,UI线程中又初始化了Looper,创建Looper的时候又创建了MessageQueue。当Handler把 Messgae发送到MessageQueue里,然后Looper循环的取出发给Handler,由Handler处理这个信息。

Handler源码分析:

new handler代码

  private Handler handler=new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
        }
    };

这样new会报警告的,查看警告是:

这个处理程序类应该是静态的,否则可能会发生泄漏(匿名的android.os.Handler)。  
由于这个处理程序被声明为一个内部类,它可以防止外部类被垃圾收集。如果处理
程序使用Looper或MessageQueue来处理主线程以外的线程,那么就没有问题了。
如果处理程序使用主线程的Looper或MessageQueue,则需要修复处理程序声明,
如下所示:将处理程序声明为静态类;在外部类中,实例化对外部类的WeakReference,
并在实例化处理程序时将该对象传递给处理程序;使用WeakReference对象对外部
类的所有成员进行引用.

new Handler直接调用的构造方法

  public Handler() {
        this(null, false);
    }

而这个构造又直接调用了

     /**
    * @hide
    */
   public Handler(Callback callback, boolean async) {
       if (FIND_POTENTIAL_LEAKS) {
           final Class<? extends Handler> klass = getClass();
           if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
                   (klass.getModifiers() & Modifier.STATIC) == 0) {
               Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
                   klass.getCanonicalName());
           }
       }

       mLooper = Looper.myLooper();
       if (mLooper == null) {
           throw new RuntimeException(
               "Can't create handler inside thread " + Thread.currentThread()
                       + " that has not called Looper.prepare()");
       }
       mQueue = mLooper.mQueue;
       mCallback = callback;
       mAsynchronous = async;
   }

@hide 方法

众所周知,Android 系统在迭代的过程中,越来越重视安全这个因素。而有
一些方法可能会涉及到系统安全、用户隐私或者其他一些原因,总之有一些
因素考量,在发布出来的时候,被 Google 标记为 @hide,表示并不希望开
发者去使用它们。而这些标记为 @hide 的方法,我们也是无法直接调用的,
只能使用反射的方式去调用它们,这本身就是不安全的操作。

先说Handler类上的参数

    private static final boolean FIND_POTENTIAL_LEAKS = false;
    private static final String TAG = "Handler";
    private static Handler MAIN_THREAD_HANDLER = null;

第一行的if判断了是有没有泄露(FIND_POTENTIAL_LEAKS=找到潜在的泄漏)默认是false的所以if里面不用看。接下

 if (FIND_POTENTIAL_LEAKS) {
            final Class<? extends Handler> klass = getClass();
            if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
                    (klass.getModifiers() & Modifier.STATIC) == 0) {
                Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
                    klass.getCanonicalName());
            }
}

Looper调用了自己的静态方法

public static @Nullable Looper myLooper() {
        return sThreadLocal.get();
    }

myLooper它返回与当前线程关联的Looper对象。如果调用线程与一个循环程序没有关联就会返回为null。
get()

public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null) {
                @SuppressWarnings("unchecked")
                T result = (T)e.value;
                return result;
            }
        }
        return setInitialValue();
    }

这个方法是,返回当前线程的此线程局部变量副本中的值。如果变量没有当前线程的值,则首先将其初始化为调用initialValue()方法返回的值。
返回到Handler的构造方法

if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread " + Thread.currentThread()
                        + " that has not called Looper.prepare()");
        }

再往后

mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;

mLooper.mQueue就是关联MessageQueue,实现了MessageQueue自动绑定。

new Handler的时候判断了被new的时候有没有泄漏。
myLooper它返回与当前线程关联的Looper对象接着判断looper是否为null。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值