Android interview (V) prepare for Android interview

  • Handler
  • Activity.runOnUiThread()
  • View.post(Runnable r)

Let's talk about the Handler mechanism

Handler is mainly composed of the following parts.

  • Handler
    Handler is a message auxiliary class, which is mainly responsible for sending various message events to the message pool Sendmessage() and the handler that handles the corresponding message event handleMessage().

  • Message
    Message is a message, which can hold any data and is equivalent to an information carrier.

  • MessageQueue
    MessageQueue, as its name implies, is a message queue. It inserts messages into the queue in time sequence, and the smallest timestamp will be processed first.

  • Looper
    Looper is responsible for reading messages from the message queue and distributing them to the corresponding Handler for processing. It is an endless loop, constantly calling messagequeue Next () reads the message. It will become blocked when there is no message distribution. Continue polling when there is a message available.

What should I pay attention to when using Handler in Android development

First of all, it is natural to create your own message queue in the worker thread. You must call Looper Prepare() and can only be called once in a thread. Of course, just creating Looper is not enough. You must also use Looper Loop() starts the message loop, otherwise it's useless to use loop.

We usually don't call it in development because the Looper of the main thread will be called by default.
In addition, there can only be one Looper object and one MessageQueue object in a thread.

The approximate standard writing is like this.

Looper.prepare();
Handler mHandler = new Handler() {
   @Override
   public void handleMessage(Message msg) {
          Log.i(TAG, "Defined in child threads Handler,And received a message...");
   }
};
Looper.loop();

Another thing that is often investigated is the possible memory leak caused by the Handler.

Possible memory leaks caused by Handler

We often write such code.

 private final Handler mHandler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
        }
    };

When you write this, you will receive a yellow warning from the compiler.

In Android, Handler classes should be static or leaks might occur, Messages enqueued on the application thread's MessageQueue also retain their target Handler. If the Handler is an inner class, its outer class will be retained as well. To avoid leaking the outer class, declare the Handler as a static nested class with a WeakReference to its outer class

In Java, both non static inner classes and anonymous inner classes implicitly hold references to their outer classes, while static inner classes do not hold references to their outer classes.

To solve this problem, when we inherit the Handler, we either put it in a separate class file or directly use the static internal class. When we need to call external Activity in the static internal class, we can directly handle it with weak references, so we probably modify the following code.

 private static final class MyHandler extends Handler{
        private final WeakReference<MainActivity> mWeakReference;

        public MyHandler(MainActivity activity){
            mWeakReference = new WeakReference<>(activity);
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            MainActivity activity = mWeakReference.get();
            if (activity != null){
                // Start writing business code
            }
        }
    }

private MyHandler mMyHandler = new MyHandler(this);

In fact, in our actual development, internal classes may be used in more than one place. In this case, we need to try to use static internal classes and weak references to solve our possible memory leakage problem.

Have you ever used HandlerThread? What's it for?

HandlerThread is a convenient class provided by Android API. Using it, we can quickly create a Thread with a Looper. With the Looper Thread, we can generate a Handler. In essence, it is an ordinary Thread with an internal Looper.

The code for creating a Handler for the sub thread mentioned above is probably like this.

new Thread(new Runnable() {
    @Override public void run() {
        // Prepare a Looper, and the corresponding MessageQueue will also be created when the Looper is created
        Looper.prepare();
        // Create a Handler and post a Message to the MessageQueue
        new Handler().post(new Runnable() {
            @Override 
            public void run() {
                  MLog.i("Handler in " + Thread.currentThread().getName());
            }
 

Keywords: Java Android Design Pattern Interview

Added by woodsy2k on Sat, 18 Dec 2021 10:49:29 +0200