Handler(原理) HandlerThread 轻松实现异步功能

来源:互联网 发布:网络平台投稿 编辑:程序博客网 时间:2024/06/05 17:08

上文说道Handler可以与任意线程绑定,这点可以帮助我们很轻松就是想异步工能


见如下代码,

public class MainActivity extends Activity {    private static final String TAG = "Handler_demo";    private  Handler myHandler;    class MyThread extends  Thread {        public  Handler handler ;        public Looper looper;        public void run(){            Looper.prepare();            looper = Looper.myLooper();            handler = new Handler(){                @Override                public void handleMessage(Message msg) {                    Log.e(TAG, "当前线程:" + Thread.currentThread());                }            };            Looper.loop();        }    }    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        MyThread mt = new MyThread();        mt.start();                myHandler = new Handler(mt.looper){            @Override            public void handleMessage(Message msg) {                Log.e(TAG, "Run IN 线程:" + Thread.currentThread());            }        };        myHandler.sendEmptyMessage(0);    }}


运行后发现包以下异常


09-27 22:41:50.577    1608-1608/com.liaoli.handleexample E/AndroidRuntime﹕ FATAL EXCEPTION: main
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.liaoli.handleexample/com.liaoli.handleexample.MainActivity}: java.lang.NullPointerException
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2211)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2261)
            at android.app.ActivityThread.access$600(ActivityThread.java:141)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1256)
            at android.os.Handler.dispatchMessage(Handler.java:99)
            at android.os.Looper.loop(Looper.java:137)
            at android.app.ActivityThread.main(ActivityThread.java:5103)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:525)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
            at dalvik.system.NativeStart.main(Native Method)
     Caused by: java.lang.NullPointerException
            at com.liaoli.handleexample.MainActivity.onCreate(MainActivity.java:52)
            at android.app.Activity.performCreate(Activity.java:5133)
            at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2175)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2261)
            at android.app.ActivityThread.access$600(ActivityThread.java:141)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1256)
            at android.os.Handler.dispatchMessage(Handler.java:99)
            at android.os.Looper.loop(Looper.java:137)
            at android.app.ActivityThread.main(ActivityThread.java:5103)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:525)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
            at dalvik.system.NativeStart.main(Native Method)

报异常的为

myHandler = new Handler(mt.looper){
这一行,也就是mt.looper为空了,这说明子线成还未来得及创建Looper实例,

此时取出来的肯定为空啊,针对这种情况,android为我们提供了一种解决方案,

提供了一个类,

public class HandlerThread extends Thread 

他是一个线程类,下面看一个简单的例子:

package com.liaoli.handlerthread_demo;import android.app.Activity;import android.os.Handler;import android.os.HandlerThread;import android.os.Message;import android.os.Bundle;import android.util.Log;public class MainActivity extends Activity {    private static final String TAG = "MainActivity";    private Handler handler;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        HandlerThread  ht = new HandlerThread("my HandlerThread");        ht.start();        handler = new Handler(ht.getLooper()){            @Override            public void handleMessage(Message msg) {                Log.e(TAG, "Run IN 线程:" + Thread.currentThread());            }        };        handler.sendEmptyMessage(0);    }}
运行后打印:

09-27 23:07:09.237  11939-11956/com.liaoli.handlerthread_demo E/MainActivity﹕ Run IN 线程:Thread[my HandlerThread,5,main]

my HandlerThread 是我们给这个HandlerThread线程的名字,这个HandlerThread的run 方法中会去创建一个与此线程绑定的Looper,


@Overridepublic void run() {    mTid = Process.myTid();    Looper.prepare();    synchronized (this) {        mLooper = Looper.myLooper();        notifyAll();    }    Process.setThreadPriority(mPriority);    onLooperPrepared();    Looper.loop();    mTid = -1;}

此时并没有报空指针,那么,他是怎么做到的呢?我们看HandlerThread的


/** * This method returns the Looper associated with this thread. If this thread not been started * or for any reason is isAlive() returns false, this method will return null. If this thread  * has been started, this method will block until the looper has been initialized.   * @return The looper. */public Looper getLooper() {    if (!isAlive()) {        return null;    }        // If the thread has been started, wait until the looper has been created.    synchronized (this) {        while (isAlive() && mLooper == null) {            try {                wait();            } catch (InterruptedException e) {            }        }    }    return mLooper;}
方法,他首先会取判断线程自己是不是活的,然后判断mLooper是否为null ,如果为空就wait(),也就是说为空就不会往下走了,器run方法中当mLooper 创建后,会取唤醒这个方

   synchronized (this) {        mLooper = Looper.myLooper();        notifyAll();    }

法,继续往下走,所以,就保证了我们在创建

 handler = new Handler(ht.getLooper()){
时,不会出现空指针的情形。


我们可一同过HandlerThread很轻松就实现一部操作,此时我们的Handler是与HandlerThread这个子线程绑定的,所以这个handler的所发送的消息都将在这个子线程中进行处理

。所以此时我们就可一将一些耗时的操作放在这个Handler 的handleMessage(Message msg)方法中进行处理。











0 0