5 Handler与子线程

5-1 自定义与线程相关的Handler 

1.在线程中通过Looper.prepare()方法创建一个与线程相关的Looper对象;
2. 在线程中通过Handler的new关键字,创建一个Handler对象,这个对象在创建的时候会关联上1中创建的Looper对象
3. 调用Looper对象的loop()方法去轮询它的MessageQueue
4. 通过其他的线程拿到这个线程的Handler对象之后调用sendMessage()之后,在这个线程中就可以进行Message的处理了。

我们一般是在主线程中创建Handler对象,在主线程中处理Message,在子线程中调用这个Handler对象的sendMessage()来发送message。所以Handler是在哪个线程创建就有哪个线程处理Message和轮询,而由别的线程负责给这个Handler发送Message。

1.注意:在主线程中创建的Handler的handleMessage()方法不要写耗时的操作,否则会导致UI卡死,因为这个handleMessage()方法是在UI线程中调用的。

package com.example.yzx;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.widget.TextView;

public class SecondActivity extends Activity {

    private Handler handler = new Handler() {
        public void handleMessage(android.os.Message msg) {
            System.out.println("UI---------" + Thread.currentThread());
        };
    };

    class MyThread extends Thread {
        public Handler handler;

        @Override
        public void run() {
            // TODO Auto-generated method stub
            Looper.prepare();
            handler = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                    // TODO Auto-generated method stub
                    System.out.println("currentThead:" + Thread.currentThread());
                }
            };
            Looper.loop();
        }
    }

    private MyThread thread;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub

        super.onCreate(savedInstanceState);
        TextView textView = new TextView(this);
        textView.setText("hellow Handler");
        setContentView(textView);
        thread = new MyThread();
        thread.start();
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        thread.handler.sendEmptyMessage(1);
        handler.sendEmptyMessage(1);
    }
}

 

5-2 HanlderThread是什么 (11:51)

HandlerThread避免多线程导致空指针问题。
handlerthread 默认【创建一个looper然后和一handler关联,那么所有的handleMessage方法是在一个子线程中进行,可以用handlerthread模拟一个异步任务,将主线程的任务发送个子线程,处理一些比较耗时操作

-----------------------------------------------------------------------------------------

1.一个Handler的创建它就会被绑定到这个线程的消息队列中,如果是在主线程创建的,那就不需要写代码来创建消息队列了,默认的消息队列会在主线程被创建。但是如果是在子线程的话,就必须在创建Handler之前先初始化线程的消息队列

2.HandlerThread继承于Thread,所以它本质就是个Thread。与普通Thread的差别就在于,它有个Looper成员变量。这个Looper其实就是对消息队列以及队列处理逻辑的封装,简单说就是 消息队列+消息循环。

在其run()方法中,调用Looper.myLooper()获得一个looper对象。
  synchronized (this) {
    mLooper = Looper.myLooper();
    notifyAll();
在创建handler时使用getLooper()方法,其实现其实是一直等待looper对象的获得。
  while (isAlive() && mLooper == null) {
    try {
      wait();
      }
   }

3.Handler在创建的时候可以指定Looper,这样通过Handler的sendMessage()方法发送出去的消息就会添加到指定Looper里面的MessageQueue里面去。在不指定Looper的情况下,Handler绑定的是创建它的线程的Looper。如果这个线程的Looper不存在,程序将抛出"Can't create handler inside thread that has not called Looper.prepare()"。

  1. 创建Handler的时指定的looper,可以是别的线程创建的。所以Handler中MessageQueue的轮询不一定非要是创建Handler的线程进行,还可以在别的线程中进行。
    这个时候我们就需要使用HandlerThread这个类来创建这个Looper了,这样消息的处理就在新创建的HandlerThread中进行。(如图)
    mThread = new HandlerThread("Handler Thread");
    mHandler = new Handler(mThread.getLooper()){
    public void handleMessage(android.os.Message msg) {
    ... };
    };

  两个线程切换的过程中,looper没有创建 会抛出控制异常
  handlerThread用来避免这个异常

package com.example.yzx;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.widget.TextView;

public class threeActivity extends Activity {

    private TextView text;
    private HandlerThread thread;
    private Handler handler;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        text = new TextView(this);
        text.setText("handler Thread");
        setContentView(text);
        thread = new HandlerThread("handler thread");
        thread.start();
        handler = new Handler(thread.getLooper()) {
            @Override
            public void handleMessage(Message msg) {
                // TODO Auto-generated method stub
                System.out.println("current thread---------->" + Thread.currentThread());

            }
        };
        handler.sendEmptyMessage(1);
    }

}

posted @ 2016-05-10 12:43  沉默的羊癫疯  阅读(137)  评论(0编辑  收藏  举报