Android 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.
--源码注释

简单说,handler就是Android类库提供的用于传递、接收和处理Message和Runnable对象的一个处理类,同时handler与线程的MessageQueue消息队列关联在一起。每个handler实例斗鱼一个单独的线程及该线程的消息队列相关联。


1.异步消息处理机制



. Message : 消息体,用于装载需要发送的对象  (Defines a message containing a description and arbitrary data object that can be sent to a {@link Handler}.)

. Looper : 用于为线程运行消息循环的类 (Class used to run a message loop for a thread. Threads by default do not have a message loop associated with them; to create one,call prepare() in the thread that is to run the loop, and then loop() to have it process messages until the loop is stopped.)

. MessageQueue : 消息队列,持有一批消息体,以待looper进行分发。 (Low-level class holding the list of messages to be dispatched by a{@link Looper}. Messages are notadded directly to a MessageQueue, but rather through {@link Handler} objects associated with the Looper.)

. Handler : handler就是Android类库提供的用于传递、接收和处理Message和Runnable对象的一个处理类


首先,要理清它们之间的内在联系。Handler和Looper对象是属于线程内部的数据,不过也提供与外部线程的访问接口,Handler就是公开给外部线程的接口,用于线程间的通信。Looper是由系统支持的用于创建和管理MessageQueue的依附于一个线程的循环处理对象,而Handler是用于操作线程内部的消息队列的,所以Handler也必须依附一个线程,而且只能是一个线程。


异步消息处理流程的简单梳理:


当应用程序开启时,系统会自动为UI线程创建一个MessageQueue(消息队列)和Looper循环处理对象。首先需要在主线程中创建一个Handler对象,并重写handlerMessage()方法。然后当子线程中需要进行UI操作时,就创建一个Message对象,并通过Handler将这条消息发送出去。之后这条消息就会被添加到MessageQueue的队列中等待被处理,而Looper则会一直尝试从MessageQueue中取出待处理消息,并找到与消息对象对应的Handler对象,然后调用Handler的handleMessage()方法。由于Handler是在主线程中创建的,所以此时handleMessage()方法中的代码也会在主线程中运行,于是我们在这里就可以安心地进行UI操作了。

在实际开发中,我们习惯用handler将在子线程中计算运行得到的数据结果包装成message对象,然后通过handler发送给主线程(UI线程)中。


2. Handler Demo Code

public class MainActivity extends AppCompatActivity {
    private MHandler mHandler = new MHandler();
    private int a = 0;
    private TextView tv_theme;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        Log.i("jon", "线程: " + Thread.currentThread().getName());
        Log.i("jon", "a : " + a);
//        startRunnable();
        startThread();
    }

    //初始化视图组件
    private void initView(){
        tv_theme = (TextView) findViewById(R.id.tv_theme);
    }

    //在主线程调用handler的post方法,运行run方法内的代码
    private void startRunnable() {
        //handler的post方法貌似是开启了一个子线程,而实际上仍然是运行在主线程之上的
        //post方法实际上是生成一个Message对象,并将runnable对象的值赋给Message对象的callback属性,
        //再将Message对象放置到消息队列当中
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                a++;
                Log.i("jon", "线程: " + Thread.currentThread().getName());
                Log.i("jon", "a: " + a);
            }
        });


    }

    //开启子线程
    private void startThread() {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                a++;
                Log.i("jon", "线程: " + Thread.currentThread().getName());
                Log.i("jon", "a: " + a);
                String str = "国王驾到!!!";
                Message msg = mHandler.obtainMessage();
                msg.obj = str;
                mHandler.sendMessage(msg); //进入主线程


            }
        });
        thread.setName("子线程1");
        thread.start();
    }

    /**
     * handler的子类,重写handlerMessage方法
     */
    class MHandler extends Handler {
        //进入主线程
        @Override
        public void handleMessage(Message msg) {
            Log.i("jon", "handler此时所在的线程: " + Thread.currentThread().getName());
            String str = (String) msg.obj;
            if(null != str){
                Log.i("jon", "handler接收到的消息是: " + str);
                tv_theme.setText(str);
            }


        }
    }


}


<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.buaa.concurrencydemo.MainActivity">

    <TextView
        android:id="@+id/tv_theme"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>

</android.support.constraint.ConstraintLayout>

3.Handler的Post方法源码分析

Handler:
	public final boolean post(Runnable r)
	{
  	 return  sendMessageDelayed(getPostMessage(r), 0);
	}
	
	private static Message getPostMessage(Runnable r) {
    		Message m = Message.obtain();
    		m.callback = r;
    		return m;
	}
Message:
	/*package*/ Runnable callback;	
/**
 * Return a new Message instance from the global pool. Allows us to
 * avoid allocating new objects in many cases.
 */
	public static Message obtain() {
    		synchronized (sPoolSync) {
        		if (sPool != null) {
            			Message m = sPool;
            			sPool = m.next;
            			m.next = null;
            			m.flags = 0; // clear in-use flag
            			sPoolSize--;
            			return m;
        		}
    		}
    		return new Message();
	}
看到这里就知道,handler的post方法只是把runnable对象赋给了Message的成员变量callback,
而callback也是一个Runnable类型的对象
Looper:
try {
    msg.target.dispatchMessage(msg);
} finally {
    if (traceTag != 0) {
        Trace.traceEnd(traceTag);
    }
}

if (logging != null) {
    logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
}

这里msg是一个Message类型的对象实例
Message:
/*package*/ Handler target

msg.target其实就是一个Handler类型的对象实例, msg.target.dispatchMessage(msg)方法其实质就是调用了handler的dispatchMessage方法,
Handler:
/**
 * Handle system messages here.
 */
public void dispatchMessage(Message msg) {
    if (msg.callback != null) {
        handleCallback(msg);
    } else {
        if (mCallback != null) {
            if (mCallback.handleMessage(msg)) {
                return;
            }
        }
        handleMessage(msg);
    }
}
private static void handleCallback(Message message) {
    message.callback.run();
}

从handlerCallback方法我可以看到,这里只是调用了Runnable对象实例的run方法,而从java基础知识的角度出发,
直接调用run方法并不会开启新的线程,所以此时代码仍然在主线程上运行。因此handler的post(Runnable runnable)方法
并不会开启新的子线程。
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值