preface

I was very busy working at Baidu last quarter. I met the OKR deadline, so I didn’t write an article for a while. Today I took the opportunity to share some of the performance optimizations we’ve seen in large Android projects.

indicators

There are many ways to quantify performance, but the most important are the following five:

  • Packet size
  • The response time
  • memory
  • CPU
  • Power consumption

Optimize performance by starting from the above five points.

Package size optimization

The apK package size is mainly determined by resource files and.class files under RES. Specific optimization measures are as follows:

  • Compress the image size and use it in your project.
  • In AndroidStudio, you can compress images in formats such as PNG to.webp format, which further reduces the image size.
  • To reduce the use of local resources as much as possible, we can consider pulling images, Lottie, so library and other resources from the server from the technical solution.
  • Use Lottie to replace the use of frame animation and reduce the use of frame animation picture resources.
  • Reduce dex file size by obfuscating to remove useless code.

Response time optimization

For users, the shorter the response time, the better. The shorter the response time, the smoother the operation.

Response speed includes startup speed — click the APP button to open the APP home page as fast as possible, and page response speed — the page can respond quickly after the user clicks, slides and other operations. APP cannot produce stutter, let alone ANR.

Specific optimization measures include:

  • Time-consuming operations should be processed by child threads and should not block the main thread.
  • SDK and other resources should be loaded lazily only when needed and not when not.
  • Avoid printing large numbers of logs in an online environment.
  • Use the inBitmap variable of bitmapFactory. Option to reuse the old Bitmap without allocating memory to the new Bitmap multiple times and destroying the old Bitmap (if the Bitmap is used frequently).
  • Optimized view rendering time:

ConstraintLayout if the view is complex, use ConstraintLayout to reduce the level of rendering.

② If the view view is relatively simple, consider using a LinearLayout horizontal layout (because the LinearLayout rendering time is shorter than ConstraintLayout, RelativeLayout).

(3) Avoid over-rendering. If there are multiple views with overlapping backgrounds, you can consider removing the view covered by the bottom layer; Theme Theme can be set to NoBackground mode.

④ If the View is created only when needed, use the ViewStub control.

  • Recyclerview list control optimization:

① View optimization of item, same as point 4.

② Increase the number of recyclerView item cache, the network request data cache, avoid the second request network.

③ Avoid the time-consuming operation in onBindViewHolder, because onBindViewHolder is executed in the main thread, and the time-consuming operation in onBindViewHolder will affect the sliding smoothness.

④ If you do not need the default recyclerView animation, delete it. (e.g. flashing animation on refresh)

⑤ When recyclerView refresh, try to use local refresh, avoid global refresh.

To check if the view is overrendered, enable the following Settings in mobile Developer mode:

Memory optimization

To reduce memory usage, you need to avoid creating too many objects, occupying too much memory, avoiding memory jitter, and avoiding memory leaks.

Memory jitter is the frequent creation and destruction of memory. During this process, the garbage collector also works frequently, affecting memory performance.

A memory leak is memory that should be collected by the GC but cannot be collected because it is still being referenced by other objects. Memory leakage is a serious problem. Too many memory leaks will cause memory overflow, resulting in OOM system errors.

The main causes of memory leakage are as follows:

  1. A singleton class referencing Context causes a memory leak.
  2. A non-static inner class referencing an external class causes a memory leak.
  3. Handler references the activity causing a memory leak.
  4. The property animation was not cancelled, causing the view to be referenced all the time and causing a memory leak.
  5. Listeners are not cancelled and callbacks are not unregistered.

Memory optimization measures include:

  • Use thread pools to reuse threads, because threads themselves take up a relatively large amount of memory, and reuse can save some memory.
  • Avoid creating objects within the onDraw method. Because onDraw is called so frequently, objects inside it are created so frequently that they take up too much memory.
  • Use StringBuilder or StringBuffer to concatenate strings to minimize String usage. (Because when concatenating strings, strings create new objects, whereas StringBuilder and StringBuffer concatenate strings.)
  • If view resources are not visible, clear them to avoid occupying memory. For example, the Bitmap. Recycle method is used to delete images and Lottie resources.
  • Optimized for memory leaks:

(1) The singleton class should refer to the Application Context, because the lifecycle of the Application Context is consistent with that of the APP. It does not cause the singleton class to refer to an activity Context so that the activity cannot be reclaimed.

② Change a non-static inner class to a static inner class so that no external class is referenced.

(3) handler: a.h andler removeCallbacksAndMessages used at the end of the call (null) to remove the queue; B. Static inner class + weak reference mode can avoid memory leakage.

static class SafeHandler extends Handler { 
     WeakReference<MainActivity> activity; 
     public SafeHandler(MainActivity mainActivity) { 
             activity = new WeakReference<MainActivity>(mainActivity); 
    } 
    @Override public void handleMessage(Message msg) { } 
}
Copy the code

④ Property animation, the end of the use of listeners should be cancelled in time, broadcast or some other external library callback should be de-registered in time.

CPU optimization

The role of CPU is to compute and process information and run programs, so the direction of optimization is to reduce CPU computing work and improve CPU computing efficiency.

Specific optimization measures include:

  • Prevent the main thread from executing time-consuming tasks, which are executed asynchronously in child threads.
  • Avoid doing a lot of time-consuming operations in the onDraw method.
  • Lazy loading and lazy initialization of information that is not needed for the time being.

Power consumption optimization

The optimized measures include:

  • Avoid frequent network requests.
  • To avoid frequent tasks, you can wait for a certain number of tasks to be executed together.
  • Avoid apps waking up the screen too often. (Frequently waking up the screen will cause the system to fail to enter hibernation and consume a lot of power)

To ensure that the performance index does not decline has always been a top priority in the development process, if the development of new functions lead to performance problems such as lag, fuselage heating power consumption surge, memory increase, it will lose users, outweighing the loss. So focusing on performance is also an invisible job for RDS. I hope this article will be helpful.

Welcome to pay attention to the public account, share with us!