HandlerThread
HandlerThread继承了Thread,它是一种可以使用Handler的Thread,它的实现也很简单,就是在run方法中通过Looper。prepare()来创建消息队列,并通过Looper.loop()来开启消息循环,这样在实际的使用中就允许在HandlerThread中创建Handler了。HandlerThread的run方法源码如下所示:
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
从HandlerThread的实现来看,他和Thread的显著不同之处在于,普通Thread主要在run方法中执行耗时任务,而HandlerThread在内部创建了消息队列,外界需要通过Handler的消息方式来通知HandlerThread执行一个具体的任务。由于Handler的run方法是一个无限循环,因此当明确不需要使用HandlerThread的时候,可以通过他的quit或者quitSafely方法来终止线程的执行,这是一个良好的编程习惯。
如下是HandlerThread的使用Demo:
public class SampleActivity extends Activity implements Handler.Callback{
private Handler mHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
HandlerThread handlerThread = new HandlerThread("BackgroundThread");
handlerThread.start();
mHandler = new Handler(handlerThread.getLooper(), this);
}
@Override
public boolean handleMessage(Message msg) {
//处理消息,主线程和子线程的消息均可进行处理
//回收消息
msg.recycle();
return true;
}
@Override
protected void onDestroy() {
super.onDestroy();
mHandler.getLooper().quit();
}
}
因为我们是通过发送消息的方式通知处理事情的,因此可以通过控制发送消息的时间来定时处理任务。
当我们需要周期性有规律有间隔的执行某个动作的时候,例如周期性ping服务器看是否断线,周期性更新一些信息,例如每几秒钟请求数据等,但是在隐藏到后台后停止查询,我们可以在onResume()方法中开始发送消息来开启任务,然后在onPause()方法中移除队列中的消息,这样就可以做到界面隐藏后不再执行任务。
如下所示为每5秒钟ping某一网站看是否响应的代码示例:
public class SampleActivity extends Activity implements Handler.Callback{
private Handler mHandler;
private final int PING_SERVER = 0x00;
private final String PING_URL = "http://www.baidu.com";
private boolean mPingServer = false;
private HandlerThread handlerThread;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
handlerThread = new HandlerThread("BackgroundThread");
handlerThread.start();
mHandler = new Handler(handlerThread.getLooper(),this);
}
@Override
public boolean handleMessage(Message msg) {
//处理消息,主线程和子线程的消息均可进行处理
switch (msg.what){
case PING_SERVER:
pingServer();
break;
}
return true;
}
private void pingServer(){
HttpURLConnection urlConnection = null;
try {
URL pingUrl = new URL(PING_URL);
urlConnection = (HttpURLConnection) pingUrl.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
if(urlConnection.getResponseCode() == 200){
Toast.makeText(SampleActivity.this,"该网站响应了",Toast.LENGTH_SHORT).show();
}
}catch (IOException e){
//当出现问题时也需要发送消息进行处理
Toast.makeText(SampleActivity.this,"!!!该网站未响应!!!",Toast.LENGTH_SHORT).show();
}finally {
if (urlConnection !=null){
urlConnection.disconnect();
}
}
if(mPingServer){
mHandler.sendEmptyMessageDelayed(PING_SERVER,5*1000);
}
}
@Override
protected void onDestroy() {
super.onDestroy();
handlerThread.quit();
}
@Override
protected void onResume() {
super.onResume();
mPingServer = true;
mHandler.sendEmptyMessage(PING_SERVER);
}
@Override
protected void onPause() {
super.onPause();
mPingServer = false;
mHandler.removeMessages(PING_SERVER);
}
}