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;
}