Handler、Looper、HandlerThread、AsyncTask到底是什么东西

看android已经3天了,感觉写代码的结构和写BS还是有巨大差别的,各种内部类,各种传参,弄得眼花缭乱的。

近2天,被Handler、Looper、HandlerThread、AsyncTask弄得几乎崩溃。知识点巨多,加之要对JAVA多线程交互调度,初看有点头大的很,但是耐心抗过去,仔细看每个类的调度关系和运行原理,到目前为止,思路已经有点清晰了。

一、明确一个知识点
首先要明确在android中,只有主线程也就是UI线程才有权利去更改Activity界面上的组件。

二、实例
先写一个HandlerActivity
package com.limaoyuan;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;

public class HandlerActivity extends Activity {
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        //利用Handler插入一个线程
        Handler handler = new Handler();
        handler.post(r);
        
        //只有在setContentView()之后,Activity才会去加载布局文件中的内容来创建Activity。
        setContentView(R.layout.main);
    }
    
    
    Runnable r = new Runnable() {	
		@Override
		public void run() {
			System.out.println("runnable thread id : " + Thread.currentThread().getId());
			try {
				Thread.sleep(5000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println("runable over");
		}
	};
}


03-03 07:53:56.883: INFO/System.out(874): activity thread id : 1
03-03 07:53:57.044: INFO/System.out(874): runnable thread id : 1
03-03 07:54:02.092: INFO/System.out(874): runable over

执行后发现,打印出的线程ID是一样的,也就是说用Handler的post方法调用的线程,
实际上就是主线程。
而已观查页面,在Activity出来5秒后,才会显示出布局文件中的TextView控件,这同样可以解释,上面说的结论,也就是Handler的post方法启动的线程其实就是主线程本身。那么这和我们要用线程的出发点就截然不同了。

那么我们将Handler的post()启动线程的方式换成传统的java thread方式,会有什么不同呢?
public class HandlerActivity extends Activity {
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        System.out.println("activity thread id : " + Thread.currentThread().getId());
        //利用Handler插入一个线程
        //Handler handler = new Handler();
        //handler.post(r);
        
        //传统java线程 
        new Thread(r).start();
        
        //只有在setContentView()之后,Activity才会去加载布局文件中的内容来创建Activity。
        setContentView(R.layout.main);
    }
    
    
    Runnable r = new Runnable() {	
		@Override
		public void run() {
			System.out.println("runnable thread id : " + Thread.currentThread().getId());
			try {
				Thread.sleep(5000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println("runable over");
		}
	};
}


03-03 07:59:51.634: INFO/System.out(1044): activity thread id : 1
03-03 07:59:51.693: INFO/System.out(1044): runnable thread id : 8
03-03 07:59:56.704: INFO/System.out(1044): runable over

从结果可以看出线程的id也不一样了,从界面上来看,当加载出activity的同时就加载出来布局文件中的TextView控件,并没有去等待5秒钟,这其实才是我们想要的结果。

但是Android中,只有主线程才能更改UI中的控件,那么怎么办呢?还好出现了一个类叫Looper类,这个类用于连接,UI线程和Handler之间的关系,当然可以不是UI线程。

Looper looper = Looper.getMainLooper(); //得到主线程Looper
Looper looper = Looper.myLooper();//得到当前线程的Looper

有了Looper以后,我们创建Handler的时候就可以把Looper做为参数加进去,从而达到与某一线程的绑定关系。
Handler handler = new Handler(looper);
然后handler.post(r)的时候这时候在runnable中的run方法中就有资格去更新UI的主页面了。

后面实在懒得写了,我的代码更具体 。

猜你喜欢

转载自shadowsocks.iteye.com/blog/939717