There are two views that need to enable asynchronous tasks to obtain data from the server. Each view creates a handler and registers it to an asynchronous task, when an error occurs when an asynchronous task retrieves data from the server, or an I/O exception or HTTP exception occurs, use this handler to notify the main view of the toast notification, use different views in the same activity according to the conditions. These views are managed through a stack. After loading a, create and register handlera TASKA and enable the asynchronous task TASKA, then, activate View B from view a (assuming that task KA is not finished at this time), create handlerb in view B, register the asynchronous task taskb, and enable task kb, handlera and handlerb are different instances of the same class. When the TASKA request server encounters an exception, handlera sends an Asynchronous Message notification to the user. View A prompts a toast notification. At this time, view a is in the stack and is not activated, while View B is in the active state, handlera and handlerb are instances of the same class. For example, can handlerb obtain the asynchronous message sent by handlera? The process is shown in:
Handlerb certainly cannot receive the message sent by handlera in TASKA. Some colleagues may say that both handlera and handlerb are Handler created in the main thread and they are associated with the main thread, each thread has a messagequeue queue, and logoff manages this queue and distributes messages. Both handlera and handlerb send messages to messagequeue in the main thread, and the two HandlerCodeThe same is true. The view where handlera is located is in the background, and view B is in the foreground. handlerb should be able to accept and process the messages sent by handlera. Test it. Although taskb is not started in view B, however, toast still pops up. Is this true?
Of course not. There are two main problems.
The first question: Can handlerb receive messages sent by handlera?
No. Check the message creation method.
Message mes = New Message ();
Mhandler. sendmessage (MES );
// ********************************
Public Final Boolean Sendmessage (Message MSG)
{
Return Sendmessagedelayed (MSG, 0 );
}
// ********************************
Public Final Boolean Sendmessagedelayed (Message MSG, Long Delaymillis)
{
If (Delaymillis < 0 ){
Delaymillis = 0 ;
}
Return Sendmessageattime (MSG, systemclock. uptimemillis () + Delaymillis );
}
// ********************************
Public Boolean Sendmessageattime (Message MSG, Long Uptimemillis)
{
Boolean Sent = False ;
Messagequeue queue = Mqueue;
If (Queue ! = Null ){
Msg.tar get = This ;
Sent = Queue. enqueuemessage (MSG, uptimemillis );
}
Else {
Runtimeexception E = New Runtimeexception (
This + " Sendmessageattime () called with no mqueue " );
Log. W ( " Logoff " , E. getmessage (), e );
}
Return Sent;
}
Through the code, we can see that the message will specify its target as the handler for sending it.
Another method:
Message mes2 = Mhandler. obtainmessage ();
Mes2.sendtotarget ();
// **********************************
Public Final Message obtainmessage ()
{
Return Message. Obtain ( This );
}
// ***********************************
Public Static Message obtain (handler h ){
Message m = Obtain ();
M.tar get = H;
Return M;
}
Both methods are the same.
Let's take a look at how messages are delivered?
Logoff will continuously poll the message queue and send the message to the response handler for processing.
Public Static Final Void Loop (){
Low.me = Mylogoff ();
Messagequeue queue = Me. mqueue;
While ( True ){
Message msg = Queue. Next (); // Might block
// If (! Me. mrun ){
// Break;
// }
If (Msg ! = Null ){
If (Msg.tar get = Null ){
// No target is a magic identifier for the quit message.
Return ;
}
If (Me. mlogging ! = Null ) Me. mlogging. println (
" >>>>> Dispatching " + Msg.tar get + " "
+ MSG. Callback + " : " + MSG. What
);
Msg.tar get. dispatchmessage (MSG );
If (Me. mlogging ! = Null ) Me. mlogging. println (
" <Finished " + Msg.tar get + " "
+ MSG. Callback );
MSG. Recycle ();
}
}
} //************************************** ***************************************
Looking at the Code marked in red above, he will call the dispatchmessage (MSG) Distribution of the target of the message. As mentioned above, the target is the handler that sends the message.
Public Void Dispatchmessage (Message MSG ){
If (Msg. Callback ! = Null ){
Handlecallback (MSG );
} Else {
If (Mcallback ! = Null ){
If (Mcallback. handlemessage (MSG )){
Return ;
}
}
Handlemessage (MSG );
}
}
At this point, handlerb will not receive the handlera message.
The second problem is that since handlerb cannot get the message of handlera, how does it play toast?
Public Static Toast maketext (context, charsequence text, Int Duration ){
Toast result = New Toast (context );
Layoutinflater inflate = (Layoutinflater)
Context. getsystemservice (context. layout_inflater_service );
View v = Inflate. Inflate (COM. Android. Internal. R. layout. transient_notification, Null );
Textview TV = (Textview) v. findviewbyid (COM. Android. Internal. R. Id. Message );
TV. settext (text );
Result. mnextview = V;
Result. mduration = Duration;
Return Result;
}
// **************************************** *****
Public Void Show (){
If (Mnextview = Null ){
Throw New Runtimeexception ( " Setview must have been called " );
}
Inotificationmanager Service = Getservice ();
String PKG = Mcontext. getpackagename ();
TN = MTN;
Try {
Service. enqueuetoast (PKG, TN, mduration );
} Catch (RemoteException e ){
// Empty
}
}
from the code above, we can see that the toast mechanism is not view-related or activity-related. Unlike the dialog mechanism, it depends on the activity that is created, toast is managed by a service called inoicationicationmanager. Although view A does not obtain the focus, view a objects still exist in the stack and handlera objects exist, so when the message arrives, he will still process the message, and the toast will pop up. Toast is a very special mechanism, so be careful when using it.