Android HandlerThread和IntentService用法和源码解析

HandlerThread

用法

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.d("LiaBin", "MainActivity onCreate tid:" + Thread.currentThread().getId());
        HandlerThread handlerThread = new HandlerThread("handler-thread");
        handlerThread.start();

        Handler handler = new Handler(handlerThread.getLooper()) {
            @Override
            public void handleMessage(Message msg) {
			    Log.d("LiaBin", "MainActivity handler tid:" + Thread.currentThread().getId());
                try {
                    Thread.sleep(20000);
					//dosomething....
					//handlerThread.quit();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
		
       handler.sendEmptyMessage(0);
    }
}

HandlerThread显而易见的好处就是不用额外自定义Thread了,同时可以通过getLooper方法获取HandlerThread线程对应的looper,
所以handler的发送消息就发送到子线程looper对应的消息队列中去了,所以此时可以用该handler来让main线程给子线程发送消息了
此时 如果打开DDMS查看这个进程,那么就会发现"handler-thread"这个线程一直存在,如果耗时操作执行完后,不做任何处理,
还是挺占用系统资源的,所以耗时操作执行完后可以执行handlerThread.quit();那么HandlerThread这个线程就会进入死亡态,不再占用系统资源

因为HandlerThread的run方法里面,最后调用的是Looper.loop(); 这是一个死循环,一直不断的取MessageQueue中的消息,所以该HandlerThread线程一直都在

源码解析

public class HandlerThread extends Thread {
    ……
    @Override
    public void run() {
        mTid = Process.myTid();
        Looper.prepare(); //为该线程绑定looper
        synchronized (this) {
            mLooper = Looper.myLooper();
            notifyAll();
        }
        Process.setThreadPriority(mPriority);
        onLooperPrepared();
        Looper.loop(); //一直开始循环取looper对应队列中的消息,所以如果不手动quit,该线程就一直存在
        mTid = -1;
    }
    
    //可以获取该线程对应的looper,构造handler的时候使用这个参数,handler中处理消息就会放在该子线程中,而不是main线程
    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;
    }
	
    //手动终止looper循环,耗时操作执行完,调用该方法可以使Looper停止不停的loop消息,从而run方法可以执行完,从而该线程终止,否则run方法一直在运行,该线程也一直在运行态
    public boolean quit() {
        Looper looper = getLooper();
        if (looper != null) {
            looper.quit();
            return true;
        }
        return false;
    }
	……
}

说明:
1. 线程只有run()方法执行完,才会终止,同时进入死亡态,looper没有终止那么run就一直在运行


IntentService

用法

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.d("LiaBin", "MainActivity onCreate tid:" + Thread.currentThread().getId() + " tname:" + Thread.currentThread().getName());
        startService(new Intent(this, MyIntentService.class)); 
    }
}

public class MyIntentService extends IntentService {

    public MyIntentService() {
        super("MyIntentService");
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d("LiaBin", "MyIntentService onCreate tid:" + Thread.currentThread().getId() + " tname:" + Thread.currentThread().getName());
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        Log.d("LiaBin", "MyIntentService onHandleIntent tid:" + Thread.currentThread().getId() + " tname:" + Thread.currentThread().getName());
        try {
            Thread.sleep(5000);
            //dosomething....
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d("LiaBin", "MyService onDestroy");
    }
}
此时耗时的操作可以放在onHandleIntent中,因为onHandleIntent是在HandlerThread子线程中被调用,不会阻塞main线程。IntentService的优点显而易见
不用在service中手动开启线程,同时耗时操作执行完后,IntentService服务自动终止,并不会一直停留在后台。同时内部开启的HandlerThread子线程也终止
IntentService的onDestroy方法中有

    @Override
    public void onDestroy() {
        mServiceLooper.quit();
    }
mServiceLooper.quit();//导致线程终止    

可以看到此时打印:
10-26 13:47:05.170 20397-20397/? D/LiaBin: MainActivity onCreate tid:1 tname:main
10-26 13:47:05.193 20397-20397/? D/LiaBin: MyIntentService onCreate tid:1 tname:main
10-26 13:47:05.194 20397-20429/? D/LiaBin: MyIntentService onHandleIntent tid:8233 tname:IntentService[MyIntentService]

源码解析

注意
1. IntentService继承自service,所以具有service的特性,每个服务都只会存在一个实例,只有第一次startService的时候才会调用onCreate,否则onStart
2. onHandleIntent在子线程中执行,所以不会阻塞main线程,耗时操作可以放在这里。同时onHandleIntent执行完后该service销毁调用onDestroy方法,onDestroy方法通知会导致子线程不再looper,子线程终止。从DDMS中也可以看到MyIntentService线程执行完耗时操作就终止
3. service还是运行在main线程中的,可以从onCreate,onStart方法中打印的还是main线程可以看出

private volatile Looper mServiceLooper;
    private volatile ServiceHandler mServiceHandler;
    private String mName;
    private boolean mRedelivery;

    private final class ServiceHandler extends Handler {
        public ServiceHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            onHandleIntent((Intent)msg.obj);
            stopSelf(msg.arg1);
        }
    }
}

onHandleIntent在handleMessage中执行,所以执行在HandlerThread子线程中
stopSelf(msg.arg1); onHandleIntent执行完后,就会停止该service,进而调用该Service的onDestroy方法,进而mServiceLooper.quit();那么就会终止HandlerThread子线程

@Override
    public void onDestroy() {
        mServiceLooper.quit();
    }
内部onCreate中创建了一个子线程,使用HandlerThread实现mServiceHandler使用该子线程的looper,所以handler是在该子线程中处理消息的。注意该service还是运行在main线程中的
@Override
    public void onCreate() {
        // TODO: It would be nice to have an option to hold a partial wakelock
        // during processing, and to have a static startService(Context, Intent)
        // method that would launch the service & hand off a wakelock.

        super.onCreate();
        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
        thread.start();

        mServiceLooper = thread.getLooper();
        mServiceHandler = new ServiceHandler(mServiceLooper);
    }

onStart方法中使用handler发送消息到HandlerThread子线程

@Override
    public void onStart(Intent intent, int startId) {
        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;
        msg.obj = intent;
        mServiceHandler.sendMessage(msg);
    }

    /**
     * You should not override this method for your IntentService. Instead,
     * override {@link #onHandleIntent}, which the system calls when the IntentService
     * receives a start request.
     * @see android.app.Service#onStartCommand
     */
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        onStart(intent, startId);
        return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
    }


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值