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

本文介绍了如何使用HandlerThread解决异步操作中的线程问题,并通过代码示例展示了如何避免空指针异常,同时提供了实现异步操作的简单方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

上文说道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,


@Override
public 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)方法中进行处理。











评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值