The Splash page for Android performance optimization should be designed in this way.
Current SplashActivity Design
At present, applications on the market will start a SplashActivity at startup. As a welcome interface, why is this design?
Personal summary has three advantages:
1. Better User Experience
For example, you can dynamically change the welcome image in the background or explicitly welcome xxx back. Sina Weibo's interaction is like this.
2. The App startup time can be reduced.
In the previous blog post, it is known that the time consumed for app startup is mainly because the business and layout complexity of MainActivity must be higher than that of displaying only one image before the Application initialization and MainActivity interface is drawn, add a Splash page that displays an image to optimize the startup of the application.
3. You can do more at application startup.
Generally, a SplashActivity is designed to stay between 2 to 4 s, or dynamically set the stay time of the Splash Interface Based on the Data Loading degree. Since the stay time is so long, of course, you can do something on the back of this interface for the rapid display of MainActivity, such as data pre-loading, sp initialization, and network requests.
Of course, you may have some questions. Can this initialization be implemented in the Application? Is the same for asynchronous data operations?
The answer is different! As mentioned in the previous article, the interface is not loaded during Application initialization. Instead, the background and layout of Theme are drawn only after the Application is created and initialized, therefore, you can use a simple Splash page to set a background welcome image for it, so that the interface can be displayed immediately, and other initialization operations can be performed on the interface, in this way, the app can be quickly started visually, and the user experience and data initialization are added.
On the contrary, if you put too much data in the Application, you will feel a delay when you click the app icon to start. You must finish all the items in the Application before entering the Activity configuration and drawing.
The shortcomings of most application Splash pages
Currently, most of the application's Splash page design uses an Activity called SplashActivity, and adds a background image to this SplashActivity, and then adds new Handler (). in a few seconds of postDelayed (), startActivity jumps into the main interface. This design looks very good. It can initialize and pre-load data in the SplashActivity and increase the application startup speed.
However, this does increase the application startup speed. After all, we can see the first frame-SplashActivity. However, after SplashActivity, we still need to adjust it to MainActivity, although some data in MainActivity can be prefetch in SplashActivity, Intent transmission is required in the middle, and the layout in MainActivity is not loaded yet. Therefore, you still need to load and draw the layout interface, then you can fill in the data. In this case, you still need to draw the interface and load the data (including Intent data transfer) to jump to the MainActivity ).
Previous design drawings of SplashActivity
In this way, the above design process can be expressed as follows:
Design of Splash pages with excellent performance and good experience
From the above design drawing, can some of these operations be removed? This can not only increase the app startup speed, but also pre-load data and separate the unnecessary data transfer and View between Splash and MainActivity.
The answer is yes. Since the SplashActivity and MainActivity are not perfect for separate operations, you can consider combining them, that is, whether to display MainActivity at the beginning, and SplashActivity becomes SplashFragment, then put a FrameLayout as the root layout to display the SplashFragment interface, so that the 2 ~ The gap time between 4s is used for network requests to load data. In this way, after the SplashFragment is displayed, remove it. In this way, the MainActivity with content is displayed, you do not have to wait for network requests to return data.
Of course, this method combines load Splash View and ContentView to load them together, which may affect the application startup time, in this case, we can use ViewStub to delay loading some views in MainActivity and subtract this influence.
The following designs:
Comparison of effects Before and After Optimization
For testing, I set the delay time of the Splash page to 2.5 s.
Before optimization:
After optimization:
After optimization, the SplashActivity is actually displayed with Fragment and removed after display. In this way, network data can be directly loaded in MainActivity, in this way, after the SplashFragment is displayed, the home page is displayed directly, saving the network loading process of the ProgressBar progress bar.
Code: <喎?http: www.bkjia.com kf ware vc " target="_blank" class="keylink"> VcD4NCjxwcmUgY2xhc3M9 "brush: java;"> private Handler mHandler = new Handler();//... final SplashFragment splashFragment = new SplashFragment(); final FragmentTransaction transaction = getFragmentManager().beginTransaction(); transaction.replace(R.id.frame, splashFragment); transaction.commit(); //... mHandler.postDelayed(new DelayRunnable(this, splashFragment, mProgressBar), 2500);//... static class DelayRunnable implements Runnable { private WeakReference contextRef; private WeakReference fragmentRef; private WeakReference progressBarRef; public DelayRunnable(Context context, SplashFragment splashFragment, ProgressBar progressBar) { contextRef = new WeakReference (context); fragmentRef = new WeakReference (splashFragment); progressBarRef = new WeakReference (progressBar); } @Override public void run() { ProgressBar progressBar = progressBarRef.get(); if (progressBar != null) progressBar.setVisibility(View.GONE); Activity context = (Activity) contextRef.get(); if (context != null) { SplashFragment splashFragment = fragmentRef.get(); if (splashFragment == null) return; final FragmentTransaction transaction = context.getFragmentManager().beginTransaction(); transaction.remove(splashFragment); transaction.commit(); } } } @Override protected void onDestroy() { super.onDestroy(); mHandler.removeCallbacksAndMessages(null); }
FrameLayout is used as the root layout of MainActivity for full screen display of SplashFragment.
For better performance, you can consider ViewStub and load additional views when the SplashFragment is displayed.
Coupling is actually very low. The Splash page has a special SplashFragment to configure, while the MainActivity only controls its loading and removal.
Several delayed loading methods of application DelayLoad
1. View. postDelayed ();
2. Handler. postDelayed ();
3. getWindow (). getDecorView (). post () {Handler. postDelay ()}
Although the first two methods both have the Delay effect, they are not the real Delay time we set, but the third method is the correct Delay. The reason is as follows:
To start the Activity interface, initialize contentView, DecorView, and ActionBar in the onCreate () method, such as contentView, inflate, we can find the corresponding controls through findViewById in this method, but at this time we just create an object for those controls, they are not added on the interface. The operations that actually add contentView to the interface are performed when the OnResume () method is executed, including the initialization of ViewRootImpl. The contentView method is used to draw the contentView after the onResume () method is executed.
Therefore, to achieve the DelayLoad lazy loading effect, you need to implement the Delay effect after all the views are drawn. The first and second method above is to execute after the first receivmtraversals, this time only makes some preparation work for the second call of the receivmtraversals () method, so that the accuracy of the Delay effect is not achieved, because the second call of receivmtraversals () it is the real layout and drawing of the View measurement, which must take time, so the first and second ways of Delay time need to be subtracted from the View Painting time.
If you want to do something after the UI is drawn, or some things must be done after the UI is drawn, you can use this method:
getWindow().getDecorView().post(new Runnable() { @Override public void run() { mHandler.post(new Runnable() { @Override public void run() { //do something } }); } });
If you want to use Delay, you can:
getWindow().getDecorView().post(new Runnable() { @Override public void run() { mHandler.postDelayed(new Runnable() { @Override public void run() { //do something } },3000); } });