HandlerThread

    • HandlerThread
    • IntentServer

HandlerThread

我们知道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; }}

IntentServer

在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源码

  1. 在onCreate()创建HandlerThread,使用其looper创建ServiceHandler(ServiceHandler其实就是handler)
  2. 当我们启动Server的时候,执行onStart()方法,得到intent并封装成Message,发送到mServiceHandler。
  3. mServiceHandler的handleMessage处理消息,调用onHandleIntent方法,也就是我们实现的抽象方法。并调用父类Server的stopSelf()停止服务,具体的停止服务会用到Binder来跟应用程序进行通信,这个后面再讲解。
  4. 调用 onDestroy()时候,退出循环mServiceLooper.quit(),这个很关键,不然线程一直运行。
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

更多相关文章

  1. 浅析Android中的消息机制-解决:Only the original thread that cr
  2. Android异步消息机制之Handler
  3. Android的Handler机制详解3_Looper.looper()不会卡死主线程
  4. android 音效处理 (2)
  5. Android之Handler用法总结
  6. Android开发之消息处理机制(一)——Handler
  7. android 音效处理 (2)
  8. Android异步加载图像小结 (含线程池,缓存方法)
  9. android 面试题集

随机推荐

  1. android 中断点续传理解
  2. android的TextView在设置ellipsize可能显
  3. Android(安卓)双开沙箱 VirtualApp 源码
  4. Android手势滑动实现ImageView缩放图片大
  5. AOP编程_Android优雅权限框架(2)Demo完全
  6. popupWindow 使用
  7. Android(安卓)其他特效展示
  8. android 利用getIdentifier()获取资源
  9. android 中ids.xml资源的使用
  10. Android(安卓)进阶——Framework 核心四