关于Handler的基础知识 Handler 详解 中提及了带有Looper的Thread,平时开发中我们只要简单的带有Looper的线程即可,而Android中已经为我们提供了这么一个Thread,那就是HandlerThread,我们先来简单的看一下这个类:
public class HandlerThread extends Thread {
int mPriority;
int mTid = -1;
Looper mLooper;
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();
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 is 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() {
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;
}
/**
* Quits the handler thread's looper.
* <p>
* Causes the handler thread's looper to terminate without processing any
* more messages in the message queue.
* </p><p>
* 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.
* </p><p class="note">
* 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.
* </p>
*
* @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.
* <p>
* 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.
* </p><p>
* 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.
* </p><p>
* 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.
* </p>
*
* @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;
}
}
代码除了注释没有几行,最主要的是在run方法中准备Looper的部分,当然还有同步的操作。接下来我们用Server结合HandlerThread模拟一个后台加载耗时操作的Demo。
声明Service
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="studio.neulion.com.tasktest">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<activity
android:name="studio.neulion.com.tasktest.ServerActivity"
android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".CommonServer" />
</application>
</manifest>
实现Service类
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
public class CommonServer extends Service
{
private ServiceHandler mServiceHandler;
private final class ServiceHandler extends Handler
{
public ServiceHandler(Looper looper)
{
super(looper);
}
@Override
public void handleMessage(Message msg)
{
super.handleMessage(msg);
/*
*这里执行到了位于HandlerThread子线程中的方法,一般是耗时的操作
*/
Log.d(ServerActivity.TAG, "HandlerThread_handleMessage: " + Thread.currentThread().getId());
long endTime = System.currentTimeMillis() + 5 * 1000;
while (System.currentTimeMillis() < endTime)
{
synchronized (this)
{
try
{
wait(endTime - System.currentTimeMillis());
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
stopSelf(msg.arg1);
}
}
@Override
public void onCreate()
{
super.onCreate();
/*
*直接获取带有Looper的子线程,HandlerThread是Android提供的带有Looper的子线程,这里通过UI线程向该HandlerThread线程发送消息
*以期完成UI线程和子线程之间的通信
*/
HandlerThread thread = new HandlerThread("ServiceStartArguments", android.os.Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
Looper serviceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(serviceLooper);
Log.i(ServerActivity.TAG, "CommonServer_onCreate");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId)
{
Log.i(ServerActivity.TAG, "CommonServer_onStartCommand");
/*
*通过UI线程向子线程发送消息,这个时候会在恰当的时机调用ServiceHandler的handleMessage()方法
*/
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
mServiceHandler.sendMessage(msg);
return super.onStartCommand(intent, flags, startId);
}
@Override
public IBinder onBind(Intent intent)
{
return null;
}
@Override
public void onDestroy()
{
super.onDestroy();
Log.i(ServerActivity.TAG, "CommonServer_onDestroy");
}
}
定义UI
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/start_server"
android:text="Start" />
</LinearLayout>
测试用例
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
public class ServerActivity extends Activity
{
public static final String TAG = "StartServer";
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_start_server);
initView();
}
private void initView()
{
final View startView = findViewById(R.id.start_server);
if (startView != null)
{
startView.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
Intent intent = new Intent(ServerActivity.this, CommonServer.class);
startService(intent);
}
});
}
}
}
测试结果
生命周期如下:
onCreate() —>> onStartCommond —–>> handleMessage —->>onDestroy
当然下次再启动service,就不会再执行onCreate()方法了。
<p>版权声明:本文为博主原创文章,未经博主允许不得转载。</p>