我们知道Handler可以进行线程间切换,如果在子线程实现looper的创建与循环,那么就实现了子线程异步操作的消息处理机制,这也就是android 为我们提供的HandlerThread
下面是HandlerThread的使用,每隔2秒更新数据。这里有几点要注意
1、使用HandlerThread的Looper()创建的Handler在接收到信息后,运行在子线程,因此不能直接更新UI
2、在使用HandlerThread的时候,退出Activity是要调用quit()停止looper
的。我们知道主线程的looper是不会阻塞线程,那是没有消息会进行休眠。但我们自己使用需要手动退出looper循环
public class HandlerThreadActivity extends Activity {
private HandlerThread myHandlerThread;
private Handler handler;
private EditText mInput;
private Handler mainHandler;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_handle_thread);
mInput = findViewById(R.id.input);
findViewById(R.id.handler_thread).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
handler.sendEmptyMessage(1);
}
});
onCreateHandle();
Intent intent = new Intent(HandlerThreadActivity.this, MyIntentServer.class);
intent.putExtra("name", "张===");
startService(intent);
mainHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
Toast.makeText(HandlerThreadActivity.this, "消息: " + msg.obj + " 线程: " + Thread.currentThread().getName(), Toast.LENGTH_LONG).show();
mInput.setText("消息: " + msg.obj + " 线程: " + Thread.currentThread().getName());
}
};
}
//线程运行耗时任务,运行完了用handler通知
private void onCreateHandle() {
//创建一个线程,线程名字:handler-thread
myHandlerThread = new HandlerThread("handler-thread");
//开启一个线程
myHandlerThread.start();
//在这个线程中创建一个handler对象
handler = new Handler(myHandlerThread.getLooper()) {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//这个方法是运行在 handler-thread 线程中的 ,可以执行耗时操作
Log.i("TAG ", "消息: " + msg.obj + " 线程: " + Thread.currentThread().getName());
mainHandler.sendMessage(mainHandler.obtainMessage(msg.what, msg.obj));
loopThread();
}
};
}
private void loopThread() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
handler.sendMessage(handler.obtainMessage(1, new Date().getTime() + ""));
}
@Override
protected void onDestroy() {
super.onDestroy();
//释放资源
myHandlerThread.quit();
mainHandler.removeCallbacksAndMessages(null);
}
}
我们再看看HandlerThread的相关源码
源码还是比较简单的,它就是一个Thread,在调用Looper的相关操作后,就具有了消息队列的功能。当使用这个Thread创建Handler后,由handler发送的消息将能保存在MessageQueue中,之后再发送到handler中进行处理。也就是HandlerThread有一个可以存放任务队列的集合
,但HandlerThread的消息处理是串行的
。相关注释看下面源码。
public class HandlerThread extends Thread {
int mPriority;
int mTid = -1;
Looper mLooper;
private @Nullable Handler mHandler;
public HandlerThread(String name) {
super(name);
mPriority = Process.THREAD_PRIORITY_DEFAULT;
}
/**
* Constructs a HandlerThread.
* @param name
* @param priority The priority to run the thread at. The value supplied must be from
* {@link android.os.Process} and not from java.lang.Thread.
*/
public HandlerThread(String name, int priority) {
super(name);
mPriority = priority;
}
/**
* Call back method that can be explicitly overridden if needed to execute some
* setup before Looper loops.
*/
protected void onLooperPrepared() {
}
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
//looper创建好后,唤醒等待线程
notifyAll();
}
//设置线程优先级
Process.setThreadPriority(mPriority);
//可以做一些循环前置
onLooperPrepared();
Looper.loop();
mTid = -1;
}
/**
* This method returns the Looper associated with this thread. If this thread not been started
* or for any reason 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() {
//如果线程已经死亡,返回null
if (!isAlive()) {
return null;
}
// If the thread has been started, wait until the looper has been created.
//如果线程已经启动,mLooper还没有创建,那么等待mLooper创建
synchronized (this) {
while (isAlive() && mLooper == null) {
try {
wait();
} catch (InterruptedException e) {
}
}
}
return mLooper;
}
/**
* @return a shared {@link Handler} associated with this thread
* 这是一个内部方法,常规下我们无法调用
* @hide
*/
@NonNull
public Handler getThreadHandler() {
if (mHandler == null) {
mHandler = new Handler(getLooper());
}
return mHandler;
}
/**
* Quits the handler thread's looper.
*
* Causes the handler thread's looper to terminate without processing any
* more messages in the message queue.
*
* Any attempt to post messages to the queue after the looper is asked to quit will fail.
* For example, the {@link Handler#sendMessage(Message)} method will return false.
*
* Using this method may be unsafe because some messages may not be delivered
* before the looper terminates. Consider using {@link #quitSafely} instead to ensure
* that all pending work is completed in an orderly manner.
*
*
* @return True if the looper looper has been asked to quit or false if the
* thread had not yet started running.
*
* @see #quitSafely
* 退出处理程序线程的循环器,不管消息有没有处理
*/
public boolean quit() {
Looper looper = getLooper();
if (looper != null) {
looper.quit();
return true;
}
return false;
}
/**
* Quits the handler thread's looper safely.
*
* Causes the handler thread's looper to terminate as soon as all remaining messages
* in the message queue that are already due to be delivered have been handled.
* Pending delayed messages with due times in the future will not be delivered.
*
* Any attempt to post messages to the queue after the looper is asked to quit will fail.
* For example, the {@link Handler#sendMessage(Message)} method will return false.
*
* If the thread has not been started or has finished (that is if
* {@link #getLooper} returns null), then false is returned.
* Otherwise the looper is asked to quit and true is returned.
*
*
* @return True if the looper looper has been asked to quit or false if the
* thread had not yet started running.
* 将没有处理完的非延迟消息进行处理,处理完后退出
*/
public boolean quitSafely() {
Looper looper = getLooper();
if (looper != null) {
looper.quitSafely();
return true;
}
return false;
}
/**
* Returns the identifier of this thread. See Process.myTid().
*/
public int getThreadId() {
return mTid;
}
}
在android中有一个HandlerThread的经典使用,那就是IntentServer。在上面我们就使用了IntentServer来打印数据.
public class MyIntentServer extends IntentService {
@Override
public void onCreate() {
super.onCreate();
Log.e("LOG", "onCreate thread id = " + Thread.currentThread().getId() + ",thread name = " + Thread.currentThread().getName());
Log.i("LOG", "===onCreate=====");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("LOG", "===onStartCommand=====");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onStart(Intent intent, int startId) {
Log.i("LOG", "===onStart=====");
super.onStart(intent, startId);
}
@Override
public void onDestroy() {
Log.i("LOG", "===onDestroy============================");
super.onDestroy();
}
@Override
public IBinder onBind(Intent intent) {
Log.i("LOG", "===onBind=====");
return super.onBind(intent);
}
@Override
public void onRebind(Intent intent) {
Log.i("LOG", "===onRebind=====");
super.onRebind(intent);
}
@Override
public boolean onUnbind(Intent intent) {
Log.i("LOG", "===onUnbind=====");
return super.onUnbind(intent);
}
/**
* Creates an IntentService. Invoked by your subclass's constructor.
*/
public MyIntentServer() {
super("MyIntentServer");
}
@Override
protected void onHandleIntent(Intent intent) {
String name = intent.getStringExtra("name");
onPrint(name);
Log.e("LOG", "onHandleIntent intent = " + intent.getStringExtra("params") + " thread id = " + Thread.currentThread().getId() + ",name = " + Thread.currentThread().getName());
}
private void onPrint(String name) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.i("LOG", "========" + Thread.currentThread().getName());
}
}, name);
thread.start();
}
}
运行一次打印的数据
根据打印可以看出,onHandleIntent()方法执行线程和onCreate()方法是不在一个线程的,并且每次点击启动startService(),执行周期都是onCreate()、 onStartCommand() 、onStart()、 onHandleIntent() 、 onDestroy(),每次执行后调用onDestroy()方法
,IntentServer处理消息的串行的,如果要在后台进行高并发建议使用Server,然后自己实现异步任务。
再看看IntentServer源码
public abstract class IntentService extends Service {
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);
}
}
/**
* Creates an IntentService. Invoked by your subclass's constructor.
*
* @param name Used to name the worker thread, important only for debugging.
*/
public IntentService(String name) {
super();
mName = name;
}
/**
* Sets intent redelivery preferences. Usually called from the constructor
* with your preferred semantics.
*
* If enabled is true,
* {@link #onStartCommand(Intent, int, int)} will return
* {@link Service#START_REDELIVER_INTENT}, so if this process dies before
* {@link #onHandleIntent(Intent)} returns, the process will be restarted
* and the intent redelivered. If multiple Intents have been sent, only
* the most recent one is guaranteed to be redelivered.
*
*
If enabled is false (the default),
* {@link #onStartCommand(Intent, int, int)} will return
* {@link Service#START_NOT_STICKY}, and if the process dies, the Intent
* dies along with it.
*/
public void setIntentRedelivery(boolean enabled) {
mRedelivery = enabled;
}
@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);
}
@Override
public void onStart(@Nullable 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(@Nullable Intent intent, int flags, int startId) {
onStart(intent, startId);
return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}
@Override
public void onDestroy() {
mServiceLooper.quit();
}
/**
* Unless you provide binding for your service, you don't need to implement this
* method, because the default implementation returns null.
* @see android.app.Service#onBind
*/
@Override
@Nullable
public IBinder onBind(Intent intent) {
return null;
}
/**
* This method is invoked on the worker thread with a request to process.
* Only one Intent is processed at a time, but the processing happens on a
* worker thread that runs independently from other application logic.
* So, if this code takes a long time, it will hold up other requests to
* the same IntentService, but it will not hold up anything else.
* When all requests have been handled, the IntentService stops itself,
* so you should not call {@link #stopSelf}.
*
* @param intent The value passed to {@link
* android.content.Context#startService(Intent)}.
* This may be null if the service is being restarted after
* its process has gone away; see
* {@link android.app.Service#onStartCommand}
* for details.
*/
@WorkerThread
protected abstract void onHandleIntent(@Nullable Intent intent);
}
到这里Handler的相关知识点就讲完了。附上其余几篇handler的理解
android-Handler源码解析
android-重新理解Handler
android-更新UI的几种方式
android-HandlerThread、IntentServer