Activity initialization performance optimization

In Android  application development, what we are most concerned about is the startup speed of Activity. It can be said that the startup speed has always been the key to whether our application can successfully attract users. Imagine the process of an interface from clicking the entrance to the actual interface display. , if it takes too long, users will lose patience and abandon the application ruthlessly. 
So how to speed up the display of an interface? We usually study the initialization process of Activity. In fact, if we create a new Activity, during its life cycle If it does nothing, its startup and display are fast enough. Because it is a system-level process control, we don't need to pay too much attention.

In the end, we will all come to a very helpless conclusion. The startup speed of Activity is actually related to our initialization time. If the initialization code is fast, the startup will be fast; if the initialization is slow, the startup will be slow.

Option 1: Initialize asynchronous thread.

Some people may think that if I put the initialization process in an asynchronous task, wouldn’t it be ok? 
Indeed, many applications do this. They start an asynchronous thread during onCreate(), then start working, and finally Put the result Handler to the main thread. 
But this still reduces the startup speed! The loss of starting the thread, the loss of time-consuming tasks preempting the CPU, and ultimately the interface will still be a few paces slower.

Option 2: postDelay(r,100)

Some people would think that it would be better if they wait until the interface is fully displayed before initializing it. 
So they use postDelay() in onCreate() to perform manual delay processing. This indeed solves the delay Initialization problem, but it introduces another problem. Is the 100ms delay time really the time when the interface initialization display is completed? For different mobile phones, this will be an unknown number. Therefore, the final effect of the solution is that in On some mobile phones, the interface is displayed very quickly, but they have to wait for a while before starting to initialize. On other mobile phones, because the delay is too short, initialization begins before the interface is fully displayed, which ultimately preempts the main thread and slows down the startup process. speed.

Option 3: Correct interface initialization completion time

By logging in each life cycle function of Activity, do you think the interface is fully displayed in onStart()? NO! Do you think the interface is fully displayed in onResume()? NO! Do you think it is in onAttachToWindow()? ? NO! When you initialize in these life cycles, you will find that the interface still needs to wait until the initialization is completed before it is displayed. Why? In the end, the idea 
of ​​​​the problem was located in Message-Loop. The main thread is completely unavailable. A loop that withstands time-consuming operations. The life cycle functions of Activity are executed sequentially through Loop messages. Therefore, if any life cycle function is stuck by a time-consuming operation, the loop cannot continue to scroll, nor can it continue to scroll. Continue to send interface rendering messages for interface drawing. I believe everyone knows that View.setVisible(VISIBLE) actually sends a rendering message instead of actually drawing the interface directly. Therefore, if this message is blocked, then The interface will still be blank.

So here’s the question? How do we make sure that the Activity must be drawn? By tracing the implementation of Loop, we found something. This function is used to 
Looper.myQueue().addIdleHandler().add an event response-Handle to the Looper for handling the Looper when it is idle. Where is the Looper? When will it be idle? The answer is that when all the initialization life cycle processes of an Activity are completed and the interface rendering is completed, there will be no other messages in the Looper. So we can start the initialization. It's not too early Not too late. 
It even starts to initialize the content very punctually when the interface is quickly displayed. 
For this purpose, we wrote a simple package:

public class BaseActivity extends Activity {
    
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Looper.myQueue().addIdleHandler(new IdleHandler() {
            @Override
            public boolean queueIdle() {
                Log.i("IdleHandler","queueIdle");
                onInit();
                return false; //false 表示只监听一次IDLE事件,之后就不会再执行这个函数了.
            }
        });
    }
    //子类重写此函数即可,而不需要在onCreate()中去初始化.
    protected void onInit() {
        Log.e("BaseActivity", "onInit");
    }
}
 
 
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

After testing , when doing time-consuming operations in onInit(), the display speed of the interface has no impact at all, because the interface has been successfully displayed on the screen before doing time-consuming operations! Of course, this does not mean that you can do 
extraordinary things in onInit(). It is a time-consuming operation. After all, it is still executed in the main thread, so the interface will be stuck until the execution is completed. During this period, if you want to click a button, I'm sorry, I am taking time, and you can't click it.

But for an initialization time of 100ms or 50ms, it is completely acceptable, because the time from the interface display to the human eye reacting to the human hand consciously starting the operation generally takes more than 1s. And within 1s, the initialization has been completed Completed. So onInit() is still only suitable for doing some small time-consuming operations. It is not suitable for synchronous tasks. You still need to put some very time-consuming operations into asynchronous tasks.

The real meaning of optimization here is to speed up the display of the Activity interface, so that the user can see the interface as soon as possible at the first glance. Then start your initialization process. Instead of waiting for the initialization to be completed before showing the user the interface.

Guess you like

Origin blog.csdn.net/H_shaohui/article/details/70228576