Analyze Handler and logoff mechanisms. With Custom Handler and logoff, you can have a more intuitive view !, Handlerlooper

Source: Internet
Author: User

Analyze Handler and logoff mechanisms. With Custom Handler and logoff, you can have a more intuitive view !, Handlerlooper

Reprinted please indicate the source: http://blog.csdn.net/liu470368500/article/details/40625333

Handler and logoff. A very high chance of being asked during the interview. Of course. I'm talking about a beginner like ours... Generally, the Handler and logoff mechanisms are explained through the source code. Here I will use Custom Handler and logoff. This gives you a more intuitive understanding of the audience. I believe that with the foundation of this blog post. Let's look at the source code of Handler and logoff. It is easier to understand.


To integrate with Android native. Here, the logic used by the Custom Handler-Logoff is basically the same as that of the system native.


Paste the MyHanlder code first:


/*** Custom Handler ** @ author lzh **/public class MyHandler {// blocking queue for inter-thread communication private BlockingQueue <MyMessage> mQueue; // CallBack private callBack CallBack for message processing; public MyHandler (callBack CallBack) {super (); MyLooper loler = MyLooper. mylogoff (); if (logoff = null) {throw new RuntimeException ("in the new thread. To create a MyHandler object, you must first call the MyLooper. prepare () method. ");} MQueue = logoff. mQueue; this. callBack = callBack ;} /*** message receipt CallBack ** @ author Administrator **/public interface CallBack {/***** process the message ** @ param msg */void handleMessage (MyMessage msg );} /*** send message ** @ param msg */public void sendMessage (MyMessage msg) consume msg.tar get = this; try {mQueue. put (msg);} catch (InterruptedException e) {}}/*** send message ** @ param msg */public void dispatchMessage (MyMessage msg) {callBack. handleMessage (msg );}}

Let's look at the mylogoff code:


Public class MyLooper {private static ThreadLocal <MyLooper> sThreadLocal = new ThreadLocal <MyLooper> (); private static MyLooper myLooper;/** a thread corresponds to a blocking queue. */Public BlockingQueue <MyMessage> mQueue = null; private MyLooper () {super (); mQueue = new LinkedBlockingQueue <MyMessage> ();} /*** prepare the corresponding mylogoff object for this thread */public static void prepare () {if (sThreadLocal. get ()! = Null) {throw new RuntimeException ("Only one MyLooper may be created per thread");} sThreadLocal. set (new myloe ();}/*** get the Looper object corresponding to the current thread ** @ return when the prepare () method is not called. ThreadLocal. the get () method returns null; */public static mylow.mylow.() {return sThreadLocal. get () ;}/ *** start the message loop here */public static void loop () {while (true) {try {myloid = myLooper (); blockingQueue <MyMessage> mQueue = myloue. the mQueue; // take () method is a blocking method. The thread will be blocked when it runs. To prepare to receive the sent message MyMessage msg = mqueue.take(includomainmsg.tar get. dispatchMessage (msg);} catch (InterruptedException e) {// This exception occurs when the thread is disabled. Exit loop return ;}}}}

Originally, MessageQueue is used in Android native. But it cannot be created. Here we only use BlockQueue instead.


Some of my friends may be unfamiliar with ThreadLocal. This is a local variable of the thread. Its set method and get () method are more interesting. Is thread-related. In which thread are you going to set variables. In which thread do you get. Therefore, the prepare () method is called in mylogoff. Create a mylogoff instance related to this thread and add it to it. In this way, only one logoff thread can be saved. There is only one blocking queue.


Next, let's look at the MyMessage code:


public class MyMessage {public int msg1;public int msg2;public int what;public Object obj;public MyHandler target;public Runnable runnable;}

Native Message is indicated by final. The Handler object stored in the Message is more important. You must rely on it to specify the Handler to which the final message should be sent for receiving. So. This is also customized.


Next we will start testing. Android does not allow blocking operations in the UI thread. Therefore, SurfaceView is used to draw a picture in a child thread to test whether inter-thread communication can be performed.


/*** Test the Custom Handler and logoff test project because of internal blocking queues. Android does not allow such blocking behaviors to appear in the main thread. * SurfaceView is used to test in the Child thread ** @ author Administrator **/public class MainActivity extends Activity {@ Overrideprotected void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); setContentView (new MySurfaceView (this);} class MySurfaceView extends SurfaceView implements SurfaceHolder. callback, CallBack {private static final String TAG = "MySurfaceView"; private SurfaceHolder mHold Er; Thread mThread; MyHandlerCreateRunnable mRunnable; private Paint mPaint; private MyHandler handler = null; public MySurfaceView (Context context) {super (context); // initialize holder: mHolder = getHolder (); mHolder. addCallback (this); mRunnable = new MyHandlerCreateRunnable (); mPaint = new Paint (); mPaint. setColor (Color. BLACK); mPaint. setAntiAlias (true); mPaint. setTextAlign (Align. CENTER); mPaint. setTextSize (45); new Thread (mRunnable ). start ();} public MySurfaceView (Context context, AttributeSet attrs, int defStyle) {super (context, attrs, defStyle);} public MySurfaceView (Context context, AttributeSet attrs) {super (context, attrs) ;}@ Overridepublic void surfaceCreated (SurfaceHolder holder) {Log. d (TAG, "= surfaceCreated ="); // mQueue = new LinkedBlockingQueue <String> (); new Thread (new MyTimerRunnable ()). start () ;}@ Ove Rridepublic void surfaceChanged (SurfaceHolder holder, int format, int width, int height) {Log. d (TAG, "= surfaceChanged =") ;}@ Overridepublic void surfaceDestroyed (SurfaceHolder holder) {Log. d (TAG, "= surfaceDestroyed =") ;}@ Overridepublic void handleMessage (MyMessage msg) {synchronized (mHolder) {Canvas mCanvas = null; System. out. println ("= lockCanvas ="); mCanvas = mHolder. lockCanvas (); // lock the canvas. Then you can draw a picture on the canvas. String content = (String) msg. obj; mCanvas. drawColor (Color. WHITE); mCanvas. drawText (content, 100,400, mPaint); mHolder. unlockCanvasAndPost (mCanvas); //}/*** scheduled message sending thread ** @ author Administrator **/class MyTimerRunnable implements Runnable {int index = 0; @ Overridepublic void run () {while (true) {MyMessage msg = new MyMessage (); msg. obj = "this is the number" + index + "; index ++; handler. sendMessage (msg); if (index> = 50) {break;} try {Thread. sleep (1000);} catch (InterruptedException e) {e. printStackTrace () ;}}}/*** create MyHandler thread ** @ author Administrator **/class MyHandlerCreateRunnable implements Runnable {@ Overridepublic void run () {MyLooper. prepare (); handler = new MyHandler (MySurfaceView. this); mylogoff. loop ();}}}}

Okay. All codes are pasted. Now let's look at it together. In MyHandlerCreateRunnable. We have saved the local variables of the current thread by calling the mylorule. prepare () method. Then create the MyHandler object. Finally, let the message cycle start. At this time. If no message arrives in this thread. It will be in the loop () method of mylogoff. The take () method of the blocked queue is blocked. Until a message arrives.


Then we are in MyTimerRunnable. Creates a message. And use the handler object created in the MyHandlerCreateRunnable thread. Send messages. For convenience. The following is a part of the code for further analysis.


/*** Send message ** @ param msg */public void sendMessage (MyMessage msg) consume msg.tar get = this; try {mQueue. put (msg);} catch (InterruptedException e ){}}

In this handler's sendMessage method. Assign values to MyHandler itself as a member variable of the msg object. Store some messages in this message queue. . The take () method in mylogoff. loop () method gets some msg objects and removes blocking. Continue running.


/*** Start the message loop here */public static void loop () {while (true) {try {myloid = myloid (); BlockingQueue <MyMessage> mQueue = myLooper. the mQueue; // take () method is a blocking method. The thread will be blocked when it runs. To prepare to receive the sent message MyMessage msg = mqueue.take(includomainmsg.tar get. dispatchMessage (msg);} catch (InterruptedException e) {// This exception occurs when the thread is disabled. Exit loop return ;}}}


After running, you can see that. Call the msg.tar get. dispatchMessage (msg) method to send the message to the MyHandler object we used to send the message.


/*** Send a message ** @ param msg */public void dispatchMessage (MyMessage msg) {callBack. handleMessage (msg );}

Then, the message object is immediately sent to the custom callback method. That is, the callback method that handler uses to process messages. HandleMessage.

So. After a long time. What is actually used to communicate between threads is actually a blocking queue... I believe this conclusion is concise and clear... This is almost exactly the same as Android's native handler-Logoff logic. So. If you understand this blog. I believe that the Handler-Logoff source code will be unobstructed...

The demo download is provided below.

Click to download demo


How to Use the Android Handler mechanism?

The Handler object is in the same thread as its caller. If a delayed operation is set in Handler, the calling thread will also be blocked. Each Handler object is bound to a logoff object, and each logoff object corresponds to a Message Queue (MessageQueue ). If the logoff object bound to the Handler is not specified when the Handler is created, The logoff object of the current thread is bound to the Handler by default.
In the main thread, you can directly use new Handler () to create a Handler object, which will be automatically bound to the logoff object of the main thread. If Handler is directly created in a non-main thread, an error will be reported, the Android system does not enable logoff in the main thread by default, and the Handler object must be bound to the logoff object. In this case, you must manually enable logoff in this thread. prepare () --> logoff. loop (), and then bind it to the Handler object; or use logoff. getMainLooper () to obtain the Looper of the main thread and bind it to this Handler object.
All the messages sent by Handler are added to the logoff MessageQueue. Handler contains two queues: thread queue and message queue. post () can add the thread object to the thread queue; Use Handler. sendMessage () can be used to add a message object to a message queue. The source code analysis shows that Handler has only one message queue, namely, MessageQueue. The thread object passed through post () will be encapsulated into a message object and passed into MessageQueue.
After a thread object is put into a Message Queue using post (), when logoff polls the thread for execution, it does not actually start a new thread separately, but it is still executed in the thread bound to the current logoff. Handler only calls the run () of the thread object. For example, the UI update command is defined in the Child thread. If the thread is directly enabled for execution, an error is reported () add it to the Logoff of the main thread and execute it to update the UI.
After you use sendMessage () to add a message object to a message queue, when logoff polls the message, handleMessage () of Handler is called to process it. Taking UI update as an example, if this method is used, the Logoff of the main thread is first bound to the Handler object, and handleMessage () is overloaded to process UI updates, then you can send a message to it.

Handler mechanism Principle

Andriod provides Handler and logoff to satisfy inter-thread communication.
Handler first-in-first-out principle.
The logoff class is used to manage Message Exchange between objects in a specific thread ).

1) loue: A thread can generate a loue object to manage the Message Queue (Message Queue) in this thread ).

2) Handler: You can construct a Handler object to communicate with logoff so as to push new messages to the Message Queue or receive messages sent by logoff from the Message Queue.

3) Message Queue: used to store messages placed by threads.

4) thread: the UI thread is usually the main thread, and Android will create a Message Queue for it when starting the program.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.