近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的主页面了。
后面实在懒得写了,我的代码更具体 。