How android multithreading communicates

 Reference: http://www.eoeandroid.com/forum.php?mod=viewthread&tid=49595&highlight=handler

            http://blog.csdn.net/itachi85/article/details/8035333

 

Android provides Handler and Looper to meet the communication between threads.

Handler is the handler of the message, which can publish or process or operate a Runnable. After the handler accepts the message, it calls handleMessage for processing.

Looper is the communication bridge between Handler and message queue. The program component passes the message to Looper through Handler, and Looper puts the message into the queue.

 

1. Several key concepts

1. MessageQueue: It is a data structure, that is, a message queue, where messages are stored. Each thread can have at most one MessageQueue data structure. When a thread is created, its MessageQueue is not automatically created. Usually a Looper object is used to manage the thread's MessageQueue. When the main thread is created, a default Looper object will be created, and the creation of the Looper object will automatically create a MessageQueue. Other non-main threads will not automatically create Looper, when needed, by calling the prepare() function.

2. Message: message object, the object stored in MessageQueue. A MessageQueue contains multiple Messages.
To obtain the Message instance object, the static method obtain Message () in the Message class is usually used. This method has multiple overloaded versions to choose from; its creation does not necessarily directly create a new instance, but starts from the MessagePool (message pool) to see if there is an available Message instance, if it exists, take it out and return it directly. If no Message instance is available in the MessagePool, a Message object is created with the given parameters. When calling removeMessages(), the Message is removed from the MessageQueue and placed in the MessagePool at the same time. In addition to the above method, you can also obtain a Message instance through the obtainMessage() of the Handler object.


3. Looper:
is the manager of MessageQueue. Each MessageQueue cannot exist without Looper. The creation of Looper objects is achieved through the prepare() function. At the same time, each Looper object is associated with a thread. The Looper object of the current thread can be obtained by calling Looper.myLooper().
When a Looper object is created, a MessageQueue object is created at the same time. Except the main thread has the default Looper, other threads do not have MessageQueue objects by default, so they cannot receive Messages. If you need to receive, define a Looper object yourself (through the prepare() function), so that the thread has its own Looper object and MessageQueue data structure.
The Looper takes out the Message from the MessageQueue and then hands it over to the Handler's handleMessage for processing. When processing is complete, call Message.recycle() to put it in the MessagePool.

4. Handler:
The handler of the message. The handler is responsible for encapsulating the information that needs to be delivered into a Message, which is achieved by calling the obtainMessage() of the handler object; the message is delivered to the Looper, which is achieved through the sendMessage() of the handler object. Then Looper puts the Message into the MessageQueue.
When the Looper object sees a Message in the MessageQueue, it broadcasts it. After the handler object receives the message, it calls the handleMessage() method of the corresponding handler object to process it.

 

2. How to pass messages between threads

 

1. The main thread sends a Message to itself

 

public class MainActivity extends Activity {
    
    private Button btnTest;
    private TextView textView;
    
    private Handler handler;
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate (savedInstanceState);
        setContentView(R.layout.main);
        
        btnTest = (Button)this.findViewById(R.id.btn_01);
        textView = (TextView)this.findViewById(R.id.view_01);
        
        btnTest.setOnClickListener(new View.OnClickListener() {
            
            @Override
            public void onClick(View arg0) {
                
                Looper looper = Looper.getMainLooper(); //The Looper object of the main thread
                //Here the handler is created with the Looper object of the main thread,
                //So, the Message sent by this handler will be passed to the MessageQueue of the main thread.
                handler = new MyHandler(looper);
                handler.removeMessages(0);
                //build the Message object
                //The first parameter: is the message code specified by yourself, which is convenient for selectively receiving in the handler
                //The second and third parameters have no meaning
                //The fourth parameter needs to encapsulate the object
                Message msg = handler.obtainMessage(1,1,1,"The main thread sent a message");
                
                handler.sendMessage(msg); //Send message
                
            }
        });
    }
    
    class MyHandler extends Handler{
        
        public MyHandler(Looper looper){
            super(looper);
        }
        
        public void handleMessage(Message msg){
            super.handleMessage(msg);
            textView.setText("I am the Handler of the main thread and received a message: "+(String)msg.obj);
        }
    }
}

 

2. Other threads send Message to the main thread

 

public class MainActivity extends Activity {
    
    private Button btnTest;
    private TextView textView;
    
    private Handler handler;
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate (savedInstanceState);
        setContentView(R.layout.main);
        
        btnTest = (Button)this.findViewById(R.id.btn_01);
        textView = (TextView)this.findViewById(R.id.view_01);
        
        btnTest.setOnClickListener(new View.OnClickListener() {
            
            @Override
            public void onClick(View arg0) {
                
                //It can be seen that a thread is started here to operate the encapsulation and sending of messages
                //In this way, the sending of the original main thread becomes the sending of other threads, is it simple? Ha ha
                new MyThread().start();    
            }
        });
    }
    
    class MyHandler extends Handler{
        
        public MyHandler(Looper looper){
            super(looper);
        }
        
        public void handleMessage(Message msg){
            super.handleMessage(msg);
            textView.setText("I am the Handler of the main thread and received a message: "+(String)msg.obj);
        }
    }
    
    //Add a thread class
    class MyThread extends Thread{
        
        public void run(){
            Looper looper = Looper.getMainLooper(); //The Looper object of the main thread
            //Here the handler is created with the Looper object of the main thread,
            //So, the Message sent by this handler will be passed to the MessageQueue of the main thread.
            handler = new MyHandler(looper);

            //build the Message object
            //The first parameter: is the message code specified by yourself, which is convenient for selectively receiving in the handler
            //The second and third parameters have no meaning
            //The fourth parameter needs to encapsulate the object
            Message msg = handler.obtainMessage(1,1,1,"Other thread sent a message");
            
            handler.sendMessage(msg); //Send message            
        }
    }
}

 

3. The main thread sends Message to other threads

 

public class MainActivity extends Activity {
    
    private Button btnTest;
    private TextView textView;
    
    private Handler handler;
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate (savedInstanceState);
        setContentView(R.layout.main);
        
        btnTest = (Button)this.findViewById(R.id.btn_01);
        textView = (TextView)this.findViewById(R.id.view_01);
        
        
        // start the thread
        new MyThread().start();    
        
        btnTest.setOnClickListener(new View.OnClickListener() {
            
            @Override
            public void onClick(View arg0) {
                //The instantiation of the handler here is in the thread
                //It is instantiated when the thread starts
                Message msg = handler.obtainMessage(1,1,1,"message sent by the main thread");
                handler.sendMessage(msg);
            }
        });
    }
    
    class MyHandler extends Handler{
        
        public MyHandler(Looper looper){
            super(looper);
        }
        
        public void handleMessage(Message msg){
            super.handleMessage(msg);
            textView.setText("I am the Handler of the main thread and received a message: "+(String)msg.obj);
        }
    }
    
    class MyThread extends Thread{
        
        public void run(){
            Looper.prepare(); //Create a Looper object for the thread to receive messages
            
            //Note: the handler here is defined in the main thread, oh, huh,
            //I saw that the handler object was used directly. Are you looking for it and where did it instantiate it?
            // see now? ? ? Oh, it can't be instantiated at the beginning, because the Looper object of the thread
            // doesn't exist yet. can now be instantiated
            //Here Looper.myLooper() gets the Looper object of the thread
            handler = new ThreadHandler(Looper.myLooper());
            
            // Do you have any doubts about this method?
            //In fact, it is a loop, which takes messages from MessageQueue in a loop.
            // Don't visit often, how do you know you have new news? ? ?
            Looper.loop();

        }
        
        //Define the message processing class in the thread class
        class ThreadHandler extends Handler{
            
            public ThreadHandler(Looper looper){
                super(looper);
            }
            
            public void handleMessage(Message msg){
                //Here the Message in the MessageQueue in the thread is processed
                //Here we return to the main thread with a message
                handler = new MyHandler(Looper.getMainLooper());
                
                Message msg2 = handler.obtainMessage(1,1,1,"Sub thread received:"+(String)msg.obj);
                
                handler.sendMessage(msg2);
            }
        }
    }
}

 

4. Other threads send messages to themselves 

 

public class MainActivity extends Activity {
    
    private Button btnTest;
    private TextView textView;
    
    private Handler handler;
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate (savedInstanceState);
        setContentView(R.layout.main);
        
        btnTest = (Button)this.findViewById(R.id.btn_01);
        textView = (TextView)this.findViewById(R.id.view_01);
        
        
        btnTest.setOnClickListener(new View.OnClickListener() {
            
            @Override
            public void onClick(View arg0) {
                // start the thread
                new MyThread().start();    
            }
        });
    }
    
    class MyHandler extends Handler{
        
        public MyHandler(Looper looper){
            super(looper);
        }
        
        public void handleMessage(Message msg){
            super.handleMessage(msg);
            textView.setText((String)msg.obj);
        }
    }    
    
    class MyThread extends Thread{
        
        public void run(){
            Looper.prepare(); //Create a Looper object for the thread
            //Here Looper.myLooper() gets the Looper object of the thread
            handler = new ThreadHandler(Looper.myLooper());
            Message msg = handler.obtainMessage(1,1,1,"myself");
            handler.sendMessage(msg);
            
            Looper.loop();

        }
        
        //Define the message processing class in the thread class
        class ThreadHandler extends Handler{
            
            public ThreadHandler(Looper looper){
                super(looper);
            }
            
            public void handleMessage(Message msg){
                //Here the Message in the MessageQueue in the thread is processed
                //Here we return to the main thread with a message
                //Join the judgment to see if it is the message sent by the thread itself
                if(msg.what == 1 && msg.obj.equals("我自己")){
                    
                    handler = new MyHandler(Looper.getMainLooper());
                    
                    Message msg2 = handler.obtainMessage(1,1,1,"Report to the main thread: I received the Message I sent to myself");
                    
                    handler.sendMessage(msg2);                
                }

            }
        }
    }
}

 

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326766688&siteId=291194637