个人学习_ Android异步消息处理机制

本文基于:
http://blog.csdn.net/guolin_blog/article/details/9991569
(不得不说,郭霖真大神@。@)

摘至:
http://blog.csdn.net/lmj623565791/article/details/47079737
1、首先Looper.prepare()在本线程中保存一个Looper实例,然后该实例中保存一个MessageQueue对象;因为Looper.prepare()在一个线程中只能调用一次,所以MessageQueue在一个线程中只会存在一个。
2、Looper.loop()会让当前线程进入一个无限循环,不端从MessageQueue的实例中读取消息,然后回调msg.target.dispatchMessage(msg)方法。
3、Handler的构造方法,会首先得到当前线程中保存的Looper实例,进而与Looper实例中的MessageQueue想关联。
4、Handler的sendMessage方法,会给msg的target赋值为handler自身,然后加入MessageQueue中。
5、在构造Handler实例时,我们会重写handleMessage方法,也就是msg.target.dispatchMessage(msg)最终调用的方法

子线程更新UI方法:
  1. Handler的post()方法
  2. View的post()方法
  3. Activity的runOnUiThread()方法
  4. Handler的sendMessage()方法

由上文网址得知:

1、2、3的方法最后都是用handler的sendMessage方法的,所以下文根据网址总结下handler的处理过程。

前言

Android UI线程是不安全,一般处理都是new Handler(),并在里面handleMessage可以在UI线程处理sendMessage发回来的信息。

注意点

  1. Handler是依附于创建时所在的线程
  2. Handler()的实现需要一个Looper,(Looper里面有一个MessageQueue在不停循环)
  3. 一个线程只有一个Looper(原因详看下文Looper.prepare源码)、也就决定了一个线程只有一个Looper.

具体过程

new Handler()源码(抄至上文网址):

public Handler() {  
    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 that has not called Looper.prepare()");  
    }  
    mQueue = mLooper.mQueue;  
    mCallback = null;  
}  

可见handler是依靠Looper.myLooper()不为null时起效。我们直接new Handler() 也没new 过Looper呀,怎么它自己就不为null生效了?

Looper.myLooper()源码:

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

所以(Looper)sThreadLocal.get()决定Handler的生死。
(Looper)sThreadLocal.get()的出生是Looper.prepare决定的。

public static final void prepare() {  
    if (sThreadLocal.get() != null) {  
        throw new RuntimeException("Only one Looper may be created per thread");  
    }  
    sThreadLocal.set(new Looper());  
} 

现在总结:

Looper.prepare()→sThreadLocal.set()!=null→sThreadLocal.get()!=null→Looper.myLooper()!=null→new Handler() 

一切的成功的基础是Looper.prepare()。那问题来了:Looper我们也没处理过啊。

其实首先,Android程序的运行入口点可以认为是android.app.ActivityThread类的main()方法;
然后main线程一建立就帮我们

Looper.prepareMainLooper(){prepare()}&&Looper.loop;

所以最后总结下

main线程handler的实现过程:
main()→Looper.prepareMainLooper()→Looper.prepare()→sThreadLocal.set()!=null→sThreadLocal.get()!=null→Looper.myLooper()!=null→new Handler() 
其他线程用Handler的实现过程:
new Thread()→Looper.prepare()→...→new Handler() 

总结:

main线程入口帮我们:

Looper.prepareMainLooper(){Looper.myLooper()};

所以 平常 我们直接:

new Handler();

其他线程没有Looper.myLooper(),所以我们需要如下写:

new Thread() → Looper.prepare()→new Handler() →Looper.loop();  

示例代码:

public class MainActivity extends Activity {  

    private Handler handler1;  

    private Handler handler2;  

    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);  
        handler1 = new Handler();  
        new Thread(new Runnable() {  
            @Override  
            public void run() {  
                Looper.prepare(); 
                handler2 = new Handler(); 
                Looper.loop();   
            }  
        }).start();  
    }  

}  

Handler的sendMessage()实现过程

进:

handler.sendMessage(msg)

queue.enqueueMessage(msg)

queue.next()!=null;

出:

Looper.loop 一直循环

if(queue.next()!=null) {handler.dispatchMessage(msg)}

handler.handleMessage(msg);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值