Android 线程通信(Handler + Message + Looper) 4 - HandlerThread

参考:

Android 线程通信(Handler + Message + Looper) 0 - 前言

android.os.HandlerThread


HandlerThreadAndroid 系统封装好的已绑定 Looper 对象的线程

下面学习 HandlerThread 类的组成和使用


主要内容:

  1. 构造器
  2. run()
  3. 线程终止
  4. 示例程序

构造器

构造函数有两个:

public HandlerThread(String name)
public HandlerThread(String name, int priority)

参数 name 表示线程名,参数 priority 表示线程优先级

优先级设置

默认优先级大小为 0

public HandlerThread(String name) {
    super(name);
    mPriority = Process.THREAD_PRIORITY_DEFAULT;
}

public static final int THREAD_PRIORITY_DEFAULT = 0;

Android 系统中的线程,优先级取值范围为 [-20, 19]-20 表示最高优先级,19 表示最低优先级)

/**
 * Set the priority of a thread, based on Linux priorities.
 * 
 * @param tid The identifier of the thread/process to change.
 * @param priority A Linux priority level, from -20 for highest scheduling
 * priority to 19 for lowest scheduling priority.
 * 
 * @throws IllegalArgumentException Throws IllegalArgumentException if
 * <var>tid</var> does not exist.
 * @throws SecurityException Throws SecurityException if your process does
 * not have permission to modify the given thread, or to use the given
 * priority.
 */
public static final native void setThreadPriority(int tid, int priority)
        throws IllegalArgumentException, SecurityException;

run()

HandlerThread 类已经在 run() 方法执行了 Looper.prepare() 方法和 Looper.loop() 方法:

@Override
public void run() {
    mTid = Process.myTid();
    Looper.prepare();
    synchronized (this) {
        mLooper = Looper.myLooper();
        notifyAll();
    }
    Process.setThreadPriority(mPriority);
    onLooperPrepared();
    Looper.loop();
    mTid = -1;
}

如果想要在中间执行一些操作,可以重写 onLooperPrepared() 方法:

/**
 * Call back method that can be explicitly overridden if needed to execute some
 * setup before Looper loops.
 */
protected void onLooperPrepared() {
}

线程终止

由于 Looper.loop() 是一个无限循环,其退出条件是消息队列已终止,必须及时调用方法 quit()

/**
 * 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;
}

调用 quit() 方法会立即终止 Looper 对象,舍弃消息队列中的消息

如果想要先完成剩余的消息再退出,可以使用方法 quitSafely()

/**
 * 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;
}

示例程序

public class HandlerThreadActivity extends AppCompatActivity {

    private MyThread thread = new MyThread("zj");

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_handler_thread);

        thread.start();

        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        Message msg = Message.obtain(thread.handler, 0, 1000);
        msg.sendToTarget();

        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        thread.quit();
    }

    class MyThread extends HandlerThread {
        private static final String TAG = "MyThread";
        public Handler handler;

        public MyThread(String name) {
            super(name);
        }

        @Override
        protected void onLooperPrepared() {
            super.onLooperPrepared();

            handler = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                    super.handleMessage(msg);
                    Log.e(TAG, "handleMessage: " + msg.arg1);
                }
            };
        }
    }
}

Note:创建子类继承 HandlerThread 后,仍旧需要调用 start() 方法

猜你喜欢

转载自blog.csdn.net/u012005313/article/details/78421028