关于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>