HandlerThread详解
抛砖引玉
在说HandlerThread之前,先看下这个。
mHandler.removeCallbacksAndMessages(null);
进去这个函数看下
public final void removeCallbacksAndMessages(Object token) {
mQueue.removeCallbacksAndMessages(this, token);
}
在到MessageQueue中看下removeCallbacksAndMessages(this, token)这个函数。
void removeCallbacksAndMessages(Handler h, Object object) {
if (h == null) {
return;
}
synchronized (this) {
Message p = mMessages;
// Remove all messages at front.
while (p != null && p.target == h
&& (object == null || p.obj == object)) {
Message n = p.next;
mMessages = n;
p.recycleUnchecked();
p = n;
}
// Remove all messages after front.
while (p != null) {
Message n = p.next;
if (n != null) {
if (n.target == h && (object == null || n.obj == object)) {
Message nn = n.next;
n.recycleUnchecked();
p.next = nn;
continue;
}
}
p = n;
}
}
}
可以看到如果参数为null的话,会将所有的Callbacks和Messages全部清除掉。
这样做的好处是在Acticity退出的时候,可以避免内存泄露。所以在退出Activity退出的时候,注意在onDestory中
mHandler.removeCallbacksAndMessages(null);
防止内存泄露。
HandlerThread优势在哪里?
Handler机制的分发中心就在Looper中的loop(),HandlerThread将loop转到子线程中处理,降低了主线程的压力,使主界面更流畅 。
在子线程中调用Looper.prepare() 为一个线程开启一个消息循环,默认情况下Android中新诞生的线程是没有开启消息循环的。(主线程除外,主线程系统会自动为其创建Looper对象,开启消息循环。) Looper对象通过MessageQueue来存放消息和事件。一个线程只能有一个Looper,对应一个MessageQueue。 然后通过Looper.loop() 让Looper开始工作,从消息队列里取消息,处理消息。
HandlerThread的使用模板
private static H mScanpackagehandler;
//创建HandlerThread
HandlerThread thread = new HandlerThread("ProxyThread");
thread.start();
//创建Handler
mScanpackagehandler = new H(thread.getLooper());
//发送信息1
Message message = mScanpackagehandler.obtainMessage();
message.what = SCAN_PAGE;
message.obj = packageName;
mScanpackagehandler.sendMessage(message);//发送message
//发送信息2
Message message = mScanpackagehandler.obtainMessage();
message.what = SCAN_PAGE1;
message.obj = packageName1;
mScanpackagehandler.sendMessage(message);//发送message
//依次从MessageQueu中取数据
private class H extends Handler {
public H(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case SCAN_PAGE:
...
break;
case SCAN_PAGE1:
...
brea;
default:
break;
}
}
}
//在onDestory的时候清除MessageQueue中的数据
public void onDestroy() {
super.onDestroy();
//释放资源
mScanpackagehandler.quit();
}
举个栗子
eg.额,代码不太规范啊,就那么个意思。
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Button mStartButton;
private TextView mTextView;
private Handler mHandler;
private static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mStartButton = (Button) findViewById(R.id.button);
mStartButton.setOnClickListener(this);
mTextView = (TextView) findViewById(R.id.textView);
Log.d(TAG, "thread.name3:" + Thread.currentThread().getName());
initHandlerThread();
Message msg = mHandler.obtainMessage();
msg.arg1 = 2;
mHandler.sendMessage(msg);
}
private void initHandlerThread() {
HandlerThread hthread = new HandlerThread("HandlerThread1");
hthread.start();
mHandler = new H(hthread.getLooper());
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mHandler != null) {
mHandler.removeCallbacksAndMessages(null);
}
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.button:
Message msg = mHandler.obtainMessage();
msg.arg1 = 1;
mHandler.sendMessage(msg);
break;
default:
break;
}
}
public class H extends Handler {
public H(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.arg1) {
case 1:
Log.d(TAG, "thread.name1:" + Thread.currentThread().getName());
runOnUiThread(new Runnable() {
@Override
public void run() {
Log.d(TAG, "thread.name11:" + Thread.currentThread().getName());
mTextView.setText("HandlerThread1");
}
});
break;
case 2:
Log.d(TAG, "thread.name2:" + Thread.currentThread().getName());
runOnUiThread(new Runnable() {
@Override
public void run() {
Log.d(TAG, "thread.name22:" + Thread.currentThread().getName());
mTextView.setText("HandlerThread11");
}
});
break;
default:
break;
}
}
}
}
HandlerThread的几点注意
HandlerThread将loop转到子线程中处理,说白了就是将分担MainLooper的工作量,降低了主线程的压力,使主界面更流畅。
开启一个线程起到多个线程的作用。处理任务是串行执行,按消息发送顺序进行处理。HandlerThread本质是一个线程,在线程内部,代码是串行处理的。
但是由于每一个任务都将以队列的方式逐个被执行到,一旦队列中有某个任务执行时间过长,那么就会导致后续的任务都会被延迟处理。
HandlerThread拥有自己的消息队列,它不会干扰或阻塞UI线程。
对于网络IO操作,HandlerThread并不适合,因为它只有一个线程,还得排队一个一个等着。