The interview will ask a knowledge point, on HandlerThread usage scenarios and how to use HandlerThread?

Foreword

Some students always ask me about school recruit this year's retreat became a gold and three silver four gold, four silver five, and what knowledge I changed ready to go review the interview, however, to be prepared very large knowledge, knowledge of which talk about today one. An article on HandlerThreadparsing

Document notes ~

Summary knowledge of PDF content GitHub subsequent updates, like the impact of gold and three silver four small partners can look and see, welcome Star
( pulled left GitHub link, you need access to relevant content such as interviews can find their own )
HTTPS: // github.com/xiangjiana/Android-MS
more complete project download. To be continued. Source. Graphic knowledge subsequent upload github.
You can click on my link I get

scenes to be used

HandlerThreadGoogle is helping us a good package, can be used to perform a number of time-consuming operations, without the need to open multiple threads, which is adopted Handlerand Looperimplemented.

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

How to use HandlerThread?

1. Create an HandlerThreadinstance of an object
  HandlerThread handlerThread = new HandlerThread("myHandlerThread" );

This parameter indicates the thread's name, I could choose.

1. Start we created HandlerThreada thread
  handlerThread.start();

Our handlerThreadand Handler bound. Remember how to bind together Handler and thread objects do? Actually very simple, it is to thread looperand Handlerbound, as follows:

  mThreadHandler = new Handler(mHandlerThread.getLooper()) { 
   @Override 
   public void handleMessage(Message msg) { 
     checkForUpdate(); 
     if(isUpdate){ 
        mThreadHandler.sendEmptyMessage(MSG_UPDATE_INFO); 
     } 
   }
  };

Note that you must follow the above three steps, in the following explanation of the source when it will analyze the reasons

Complete test code as follows

  public class MainActivity extends AppCompatActivity { 
     private static final int MSG_UPDATE_INFO = 0x100; 
     Handler mMainHandler = new Handler(); 
     private TextView mTv; 
     private Handler mThreadHandler; 
     private HandlerThread mHandlerThread; 
     private boolean isUpdate = true; 

     @Override 
     protected void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.activity_main); 
        mTv = (TextView) findViewById(R.id.tv); 
        initHandlerThread(); 
     }

     private void initHandlerThread() {
        mHandlerThread = new HandlerThread("xujun"); 
        mHandlerThread.start(); 
        mThreadHandler = new Handler(mHandlerThread.getLooper()) { 

          @Override 
          public void handleMessage(Message msg) { 
             checkForUpdate(); 
             if (isUpdate) { 
                 mThreadHandler.sendEmptyMessage(MSG_UPDATE_I NFO); 
             } 
          } 
      };
   }
  
   /**
    * 模拟从服务器解析数据 
    */ 
    private void checkForUpdate() { 
       try {
           //模拟耗时 
           Thread.sleep(1200); 
           mMainHandler.post(new Runnable() { 
                @Override 
                public void run() { 
                   String result = "实时更新中,当前股票行情:<font color='red'>%d</font>"; 
                   result = String.format(result, (int) (Math.r andom() * 5000 + 1000)); 
                   mTv.setText(Html.fromHtml(result)); 
                } 
           }); 
    } catch (InterruptedException e) { 
           e.printStackTrace(); 
    } 
  }

   @Override 
   protected void onResume() { 
      isUpdate = true;
      super.onResume(); 
      mThreadHandler.sendEmptyMessage(MSG_UPDATE_INFO); 
    }

    @Override 
    protected void onPause() { 
       super.onPause(); 
       isUpdate = false; 
       mThreadHandler.removeMessages(MSG_UPDATE_INFO); 
    }

    @Override 
    protected void onDestroy() { 
       super.onDestroy(); 
       mHandlerThread.quit(); 
       mMainHandler.removeCallbacksAndMessages(null); 
    }
   }

Run the above test code, the following effects can be seen in FIG. (Example not appropriate, the scene is used mainly in handleMessagethe time-consuming operation)

HandlerThreadSource code analysis

Official source code is as follows, based on sdk23, you can see, only a hundred lines of code.

  public class HandlerThread extends Thread {
     int mPriority; 
     int mTid = -1; 
     Looper mLooper; 

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

     public HandlerThread(String name, int priority) { 
        super(name); 
        mPriority = priority; 
     }
     
     /**
      * Call back method that can be explicitly overridden if nee ded to execute some 
      * setup before Looper loops. 
      */ 
      protected void onLooperPrepared() { 
      }

      @Override 
      public void run() { 
         mTid = Process.myTid(); 
         Looper.prepare(); 
         //持有锁机制来获得当前线程的Looper对象 
         synchronized (this) { 
             mLooper = Looper.myLooper(); 
             //发出通知,当前线程已经创建mLooper对象成功,这里主要是通知g etLooper方法中的wait notifyAll(); 
         }
         //设置线程的优先级别 
         Process.setThreadPriority(mPriority); 
         //这里默认是空方法的实现,我们可以重写这个方法来做一些线程开始之前 的准备,方便扩展 
         onLooperPrepared(); 
         Looper.loop(); 
         mTid = -1;
     }
     public Looper getLooper() { 
        if (!isAlive()) { 
            return null;
        }
       // 直到线程创建完Looper之后才能获得Looper对象,Looper未创建成功 ,阻塞 synchronized (this) { 
             while (isAlive() && mLooper == null) { 
                try {
                    wait(); 
                } catch (InterruptedException e) { 
                } 
             } 
       }
       return mLooper; 
     }

     public boolean quit() { 
       Looper looper = getLooper(); 
       if (looper != null) { 
           looper.quit(); 
           return true;
       }
       return false; 
     }
     
     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; 
      } 
  }

1) First, let's look at its construction method

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

  public HandlerThread(String name, int priority) { 
     super(name); 
     mPriority = priority; 
  }

There are two constructors, one parameter and two parameters, name represents the name of the current thread, prioritythread priority level

2) Then we look at the run()way in which we can see that we run method initializes a Looper, and set the thread's priority

  public void run() { 
     mTid = Process.myTid(); 
     Looper.prepare(); 
     //持有锁机制来获得当前线程的Looper对象 
     synchronized (this) { 
         mLooper = Looper.myLooper(); 
         //发出通知,当前线程已经创建mLooper对象成功,这里主要是通知getLo oper方法中的wait notifyAll(); 
     }
     //设置线程的优先级别 
     Process.setThreadPriority(mPriority); 
     //这里默认是空方法的实现,我们可以重写这个方法来做一些线程开始之前的准备 ,方便扩展 
     onLooperPrepared(); 
     Looper.loop(); 
     mTid = -1; 
  }
  • Remember earlier we said that we use HandlerThreadwhen we must call the start () method, then we can put our HandlerThreadand our handler tied to it? Actually, the reason is that we are in the run()method began our initialization looper, which we call HandlerThreadthe start()when the method, the thread to the virtual machine scheduling, call the run method automatically by a virtual machine
  mHandlerThread.start(); 
  mThreadHandler = new Handler(mHandlerThread.getLooper()) { 
       @Override 
       public void handleMessage(Message msg) { 
          checkForUpdate(); 
          if(isUpdate){ 
             mThreadHandler.sendEmptyMessage(MSG_UPDATE_INFO);
          } 
       } 
  };
  • Here, we use lock mechanism and why notifyAll(); because we can from getLooper()know methods
  public Looper getLooper() { 
     if (!isAlive()) { 
        return null; 
     }
     // 直到线程创建完Looper之后才能获得Looper对象,Looper未创建成功,阻塞 
     synchronized (this) { 
        while (isAlive() && mLooper == null) { 
             try {
                 wait(); 
             } catch (InterruptedException e) { 
             } 
        } 
     }
     return mLooper; 
  }

Summary: in obtaining mLoopera problem when a synchronization object only when the thread is created successfully and Looperafter the object is created successfully also to get mLoopervalue. Wait wait method and the run method of this notifyAllmethod together to complete synchronization problems.

3) Then we look at the quitmethods and quitSafemethods

  //调用这个方法退出Looper消息循环,及退出线程 
  public boolean quit() { 
     Looper looper = getLooper(); 
     if (looper != null) {
         looper.quit(); 
         return true; 
     }
     return false; 
  }
  //调用这个方法安全地退出线程 
  @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) 
  public boolean quitSafely() { 
     Looper looper = getLooper(); 
     if (looper != null) { 
         looper.quitSafely(); 
         return true; 
     }
     return false;
  }

Tracking these two methods is easy to know only two methods will eventually call MessageQueuethe quit(boolean safe)method

  void quit(boolean safe) { 
       if (!mQuitAllowed) { throw new IllegalStateException("Main thread not allowed to quit."); 
       }
       synchronized (this) { 
           if (mQuitting) { 
               return; 
           }
           mQuitting = true; 
           //安全退出调用这个方法 
           if (safe) { 
               removeAllFutureMessagesLocked(); 
           } else {//不安全退出调用这个方法 
               removeAllMessagesLocked(); 
           }
           // We can assume mPtr != 0 because mQuitting was previou sly false.nativeWake(mPtr); 
       } 
  }

Unsafe calls removeAllMessagesLocked(); this method, we look at how to deal with this method is, in fact, is to go through Messagethe list, remove all the callback information, and reset to null.

  private void removeAllMessagesLocked() { 
     Message p = mMessages; 
     while (p != null) { 
           Message n = p.next; 
           p.recycleUnchecked(); 
           p = n; 
     }
     mMessages = null; 
  }

Safely calls removeAllFutureMessagesLocked(); this method, it will be based on Message.whenthis property to determine whether our current message queue is processing the message, no message is being processed, then simply remove all callbacks being processed, then wait for the message processing is complete and then exit the loop . So, to say quitSafe()it is safe, but quit()the method is not safe, because the quit method regardless of whether the message is being processed, directly remove all callbacks.

  private void removeAllFutureMessagesLocked() { 
     final long now = SystemClock.uptimeMillis(); 
     Message p = mMessages; 
     if (p != null) { 
        //判断当前队列中的消息是否正在处理这个消息,没有的话,直接移除所有 回调 
        if (p.when > now) { 
            removeAllMessagesLocked(); 
        } else {//正在处理的话,等待该消息处理处理完毕再退出该循环 
            Message n; 
            for (;;) { 
                n = p.next;
                if (n == null) { 
                    return; 
                }
                if (n.when > now) { 
                    break; 
                }
                p = n; 
           }
           p.next = null; 
           do {
               p = n; 
               n = p.next; 
               p.recycleUnchecked(); 
           } while (n != null); 
        } 
     } 
  }

Document notes ~

Summary knowledge of PDF content GitHub subsequent updates, like the impact of gold and three silver four small partners can look and see, welcome Star
( pulled left GitHub link, you need access to relevant content such as interviews can find their own )
HTTPS: // github.com/xiangjiana/Android-MS
more complete project download. To be continued. Source. Graphic knowledge subsequent upload github.
You can click on my link I get

Published 251 original articles · won praise 33 · views 50000 +

Guess you like

Origin blog.csdn.net/Android_SE/article/details/104415860