android的UI操作不是线程安全的,同时也只有主线程才能够操作UI,同时主线程对于UI操作有一定的时间限制(最长5秒)。为了能够做一些比较耗时的操作(比如下载、打开大文件等),android提供了一些列机制。《android基础知识02——线程安全》系列文章就是参考了网上许多网友的文章后,整理出来的一个系列,介绍了主要的方法。分别如下:
android基础知识02——线程安全2:handler、message、runnable
android基础知识02——线程安全3:Message,MessageQueue,Handler,Looper
android基础知识02——线程安全4:HandlerThread
android基础知识02——线程安全5: AsyncTask
在前面介绍的线程安全中,为了操作主线程的UI,使用子线程进行处理。在android开发中,还可以使用另外两种方法进行处理:
HandlerThread
AsyncTask
本文先介绍HandlerThread。
HandlerThread继承于Thread,所以它本质就是个Thread。与普通Thread的差别就在于,它有个Looper成员变量。这个Looper其实就是对消息队列以及队列处理逻辑的封装,简单说就是 消息队列+消息循环。
当我们需要一个工作者线程,而不是把它当作一次性消耗品,用过即废弃的话,就可以使用它。
其使用方法为:
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- HandlerThread hThread=new HandlerThread("myThread");
- hThread.start();
- myhandler myhandler=new myhandler(hThread.getLooper());
- Message msg=myhandler.obtainMessage();
- msg.sendToTarget();//把 Message发送到目标对象,目标对象就是生成msg的目标对象。
- }
- class myhandler extends Handler{
- public myhandler(Looper looper){
- super(looper);
- }
- public void handleMessage(Message msg) {
- Log.e("这是新线程", "》》》》》》》》》》》》》》》》》新线程的测试");
- }
- }
注:这里需要handlerThread.start();先启动线程 才能 handlerThread.getLooper() 获取当前线程的Looper。
HandlerThread使用是比较简单的,我们翻翻它的源码,也是很简单的。
- /**
- * Handy class for starting a new thread that has a looper. The looper can then be
- * used to create handler classes. Note that start() must still be called.
- */
- public class HandlerThread extends Thread {
- private int mPriority;
- private int mTid = -1;
- private 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 over ridden if needed to execute some
- * setup before Looper loops.
- */
- protected void onLooperPrepared() {
- }
- public void run() {
- mTid = Process.myTid();
- Looper.prepare();
- synchronized (this) {
- mLooper = Looper.myLooper();
- Process.setThreadPriority(mPriority);
- notifyAll();
- }
- 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;
- }
- /**
- * Ask the currently running looper to quit. 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.
- */
- public boolean quit() {
- Looper looper = getLooper();
- if (looper != null) {
- looper.quit();
- return true;
- }
- return false;
- }
- /**
- * Returns the identifier of this thread. See Process.myTid().
- */
- public int getThreadId() {
- return mTid;
- }
- }