##### Read for five minutes at 10 o ‘clock every day, and learn with you for a lifetime.

1.OOM and crash optimization

1.2 ANR optimization

  • The generation of ANR needs to meet three conditions
    • Main thread: ANR is generated only if the main thread response of the application process times out;
    • Timeout time: The timeout time varies depending on the context in which the ANR is generated, but ANR will occur as long as there is no response within this time limit;
    • Input events/Specific operations: Input events refer to device input events such as buttons and touch screens. Specific operations refer to functions in the life cycle of BroadcastReceiver and Service. The causes of ANR vary depending on the context in which ANR is generated.
  • ANR optimization specific measures
    • Put all time-consuming operations such as network access, Socket communication, querying a large number of SQL statements, complex logic calculations, etc. into child threads, and then update the UI via handler.sendMessage, runonUIThread, AsyncTask, etc. Make sure the user interface is smooth at all costs. If a time-consuming operation requires the user to wait, a degree bar can be displayed on the interface.
    • Use AsyncTask to process time-consuming I/O operations. In some synchronous operations, the main thread may be locked and need to wait for other threads to release the corresponding lock to continue execution, which has a certain ANR risk. In this case, asynchronous threads can also be used to execute the corresponding logic. Also, avoid deadlocks.
    • Instead of blocking the main Thread with thread.wait () or thread.sleep (), use handlers to process worker Thread results.
    • Try to avoid time-consuming code in the Activity’s onCreate and onResume callbacks
    • IntentService is recommended for onReceive code in BroadcastReceiver to minimize time consumption.
    • The lifecycle functions of each component should not have time-consuming operations, even for a background Service or ContentProvider. When the application is running in the background, its onCreate() will not have user input causing an event to go unanswered ANR. However, long execution time can also cause ANR of Service and ANR of ContentProvider

2. Memory leak optimization

  • Memory detection the first way: code to obtain memory

    /** * Memory usage check: You can call the system's getMemoryInfo() to get the current memory usage */ private void initMemoryInfo() {ActivityManager ActivityManager = (ActivityManager) Utils.getApp() .getSystemService(Context.ACTIVITY_SERVICE); ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo(); if (activityManager ! = null) { activityManager.getMemoryInfo(memoryInfo); LogUtils.d("totalMem=" + memoryInfo.totalMem + ",availMem=" + memoryInfo.availMem); if (! Memoryinfo.lowmemory) {// running in a lowMemory environment}}}Copy the code
  • The second type of memory detection: Leakcanary tool

    • LeakCanary works by monitoring each activity, detecting the reference in the background thread after the Activity ondeStory, and then gc it after a while. If the reference is still there, the memory stack is dumped and parsed for visual display.

The 2.0 animation resource was not released

  • The problem code

    public class LeakActivity extends AppCompatActivity { private TextView textView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_leak); textView = (TextView)findViewById(R.id.text_view); ObjectAnimator ObjectAnimator = ObjectAnimator. OfFloat (textView, "rotation", 0360); objectAnimator.setRepeatCount(ValueAnimator.INFINITE); objectAnimator.start(); }}Copy the code
  • The solution

    • In property animation, there is an infinite loop animation. If you play this animation in an Activity and stop it in onDestroy, the animation will continue playing and the Activity will be held by the View, preventing it from being released. To solve this problem, onDestroy calls ObjectAnimator.cancel () in the early Activity to stop the animation.
    @Override
    protected void onDestroy() {
        super.onDestroy();
        mAnimator.cancel();
    }
    
    Copy the code

2.1 Incorrect use of simple interest

  • Singletons often need to hold Context objects in development, and memory leaks can occur if the Context object is held with a shorter lifetime than the singletons, or if the Context cannot be released for recycling. For example, a memory leak occurs when an Activity is called in an Activity and then closed.
  • Solutions:
    • To ensure that the Context has the same lifecycle as the AppLication, modify the following code:
    • this.mContext = context.getApplicationContext();
    • 1. If the Application Context is passed in, there will be no problem since the Application lifecycle is the entire Application lifecycle.
    • 2. If the Activity Context is passed in and the Activity exits, the singleton holds the reference to the Context and its lifetime is equal to the lifetime of the application. So when the current Activity exits, its memory is not reclaimed, causing a leak.

2.2 Incorrect use of static variables

  • Using static methods is very convenient. However, you are advised not to globalize objects. Globalized variables must be static. Globalized variables or objects cause memory leaks!
  • Cause analysis,
    • The inner class AClass implicitly holds a reference to the outer class Activity, which is called in the Activity’s onCreate method. AClass is statically typed and will not be garbage collected. The Activity cannot be garbage collected when it executes onDestory because AClass holds a reference to it. So the Activity is always held by AClass and cannot be reclaimed, causing a memory leak.

2.3 Handler Memory leakage

  • Analyze the causes of memory leakage
    • Create an mHandler object as an inner class, and then the mHandler will implicitly hold a reference to an external class object in this case MainActivity, and when you execute the postDelayed method, that will load your Handler into a Message, The Message is pushed to a MessageQueue, which polls for processing messages in a Looper thread, so when the Activity exits there are unprocessed messages in the Message queue or messages being processed. Message in the Message queue holds a reference to the mHandler instance, which in turn holds a reference to the Activity. As a result, the Activity’s memory resources cannot be reclaimed in time, causing a memory leak.
  • There are two main points to address Handler memory leaks
    • There are delayed Messages to remove the Messages listener while the Activity is being destroyed
    • Leaks caused by anonymous inner classes are changed to anonymous static inner classes, and weak references are made to the context or Activity.

2.4 Memory Leaks caused by threads

  • In the early days, most time-consuming operations were handled by Thread+Handler, which was gradually replaced by AsyncTask. Until now, asynchronous operations are handled by RxJava.
  • Analyze the causes of memory leakage
    • During a time-consuming operation, the MainActivity may exit before it finishes processing, but AsyncTask still holds a reference to the MainActivity, causing the MainActivity to fail to reclaim and causing a memory leak.
  • The solution
    • When using AsyncTask, cancel the corresponding task asynctask.cancel () method during Activity destruction to avoid wasting resources in the background and thus avoiding memory leaks.

2.5 Non-static inner classes

  • Memory leaks caused by non-static inner classes creating static instances. This may be used when an Activity is being started frequently to avoid creating the same data resource repeatedly.

  • The problem code

    private static TestResource mResource = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if(mResource == null){ mResource = new TestResource(); }} Class TestResource {// code inside reference context, activity. this will cause memory leak}Copy the code
  • The solution

    • Make this inner class a static inner class or extract it and encapsulate it as a singleton. If Context is required, use the Application Context recommended above.
  • To analyze problems

    • This creates a singleton of a non-static inner class inside the Activity, whose data is used each time the Activity is started. This avoids duplication of resources, but it can cause memory leaks because non-static inner classes hold references to external classes by default. The non-static inner class creates a static instance that has a lifetime as long as the application’s. As a result, the static instance will always hold references to the Activity, causing the Activity’s memory resources to be recycled.

2.6 Listeners are not Removed

  • The problem code
/ / add to monitor, On the collection of TV inside. GetViewTreeObserver (.) addOnWindowFocusChangeListener (new ViewTreeObserver. OnWindowFocusChangeListener () { @override public void onWindowFocusChanged(Boolean b) {// When the view is loaded, calculate the width of the view. }});Copy the code
  • The solution
/ / after the calculation, must remove this monitor TV. GetViewTreeObserver () removeOnWindowFocusChangeListener (this);Copy the code
  • Matters needing attention:

    tv.setOnClickListener(); / / to monitor execution of the recycled object, without considering the memory leak TV. GetViewTreeObserver () addOnWindowFocusChangeListene, monitoring, add in the collection, need to consider a memory leakCopy the code

2.7 Holding an Activity reference

2.8 Resources are not shut down

  • Close it when using IO, File streams, or RESOURCES such as Sqlite and Cursor. These resources usually use buffers for read and write operations. If they are not closed in time, these buffer objects will always be occupied and cannot be released, resulting in memory leaks. So we turn them off when they are no longer needed, so that the buffer can be released in time to avoid memory leaks.
  • BroadcastReceiver, ContentObserver, FileObserver, Cursor, A Callback must be unregistered or closed after the Activity onDestroy or the end of a class lifecycle, otherwise the Activity class will be strongly referenced by the system and will not be recycled. It is important to note that closed statements must be closed in finally, otherwise the activity may leak because the exception does not close the resource.

2.9 Other Reasons

  • Memory leaks due to improper use of static collections
    • Sometimes we need to add objects to a collection container (such as an ArrayList), and when an object is no longer needed, the GC will not be able to reclaim the object if the reference to the object is not removed from the collection. If the collection is static, the memory leak is even worse. Therefore, when an object is no longer needed, it needs to be actively removed from the collection.
  • Memory leaks occur when unneeded listeners are not removed
    • The problem code

      / / add to monitor, On the collection of TV inside. GetViewTreeObserver (.) addOnWindowFocusChangeListener (new ViewTreeObserver. OnWindowFocusChangeListener () { @override public void onWindowFocusChanged(Boolean b) {// When the view is loaded, calculate the width of the view. }});Copy the code
    • The solution

      / / after the calculation, must remove this monitor TV. GetViewTreeObserver () removeOnWindowFocusChangeListener (this);Copy the code
    • Matters needing attention:

      tv.setOnClickListener(); / / to monitor execution of the recycled object, without considering the memory leak TV. GetViewTreeObserver () addOnWindowFocusChangeListene, monitoring, add in the collection, need to consider a memory leakCopy the code

3. Layout optimization

3.1 include optimization

  • Reuse layout files
    • Tags allow the introduction of a layout within a layout, so for example, if all the interfaces of our application have a common section, it is best to extract this common section into a separate layout, and then reference this common section in the layout file of each interface.
    • If we want to override the layout property in the tag, we must also override the layout_width and layout_height properties, otherwise the overlay effect will not work.
    • Tags are used as an auxiliary extension of tags to prevent unnecessary layout nesting when referencing layout files. The more nested the layout, the more time it takes to parse and the worse the performance. So write the layout file with as few nested layers as possible.
    • For example, use a layout inside a LinearLayout. There is also a LinearLayout inside, so there is actually redundant layout nesting, use merge to solve the problem.

3.2 ViewStub optimization

  • The layout is loaded only when needed [ViewStub]
    • Elements in a layout are not displayed together. In general, only some of the most common elements are displayed, while the less common elements are displayed only when the user performs a specific action.
    • For example, instead of filling in all the information, there is an option to add more fields. Additional elements are displayed only when the user needs to add additional information. For VISIBLE performance to be mediocre, you can use the ViewStub.
    • A ViewStub is also a View, but it has no size, no drawing function, and no involvement in layout. It has very low resource consumption and can be considered to have no impact on performance.
    • The layout loaded by the ViewStub does not use tags, so this can result in redundant nested structures in the layout that is loaded out.
  • Custom global state manager [make full use of ViewStub]
    • For multi-state, there are data, empty data, load failure, load exception, network exception and so on. For empty data, load failure, abnormal use of viewStub layout, one click to set the custom layout, is also an optimization.
    • Project Address:

3.3 the merge optimization

  • The view hierarchy
    • This tag plays a very important role in the structure of the UI by eliminating redundant layers and optimizing the UI. But there is a disadvantage, can not preview the layout effect!

3.4 Other Suggestions

  • Overdraw too many overlapping backgrounds
    • The easiest way to fix this problem is to check the backgrounds you have in your layout and code. Some backgrounds are hidden underneath and will never show up. This unnecessary background should be removed because it could seriously affect the performance of your app. If USES is the background of the selector, the color is set to “normal state @ android: color/transparent”, can also solve the problem.
  • Avoid complex Layout hierarchies
    • Hierarchy Viewer, a layout tool provided by Android, is recommended to check and optimize the layout. The first suggestion is that if a nested linear layout deepens the layout level, use a relative layout instead. The second tip: use tags to combine layouts. The third tip is to reuse layouts with tags. Extracting common layouts makes layout logic clearer. Keep in mind that the ultimate goal of these suggestions is to make your Layout wide and shallow in the Hierarchy Viewer, not narrow and deep.
    • Summary: Consider using merge and include, ViewStub. Keep the layout as shallow and flat as possible, and use RelactivityLayout as little as possible for the root layout, because RelactivityLayout requires two measurements each time.

4. Code optimization

  • It’s all a few minor optimizations, and you don’t see any significant improvement in performance. The use of appropriate algorithms and data structures is the most important means of optimizing program performance.

4.1 It is recommended to use Lint checks to remove invalid code

  • Lint removes invalid resources and code
    • How do I detect which images are not used
      • Click the Analyze -> Run Inspection by Name -> unused resources -> Moudule ‘app’ -> OK to search for unused XML and images:
    • How do I detect which code is invalid
      • For Android Studio Lint, click the menu bar Analyze -> Run Inspection by Name -> unused declaration -> Moudule ‘app’ -> OK

4.2 Code specification optimization

  • Avoid creating unnecessary objects unnecessary objects should be avoided:
    • If you have strings that need to be concatenated, use StringBuffer or StringBuilder to concatenate strings in preference to the plus concatenator, because using the plus concatenator creates extra objects. The longer the concatenated string, the worse the performance of the plus concatenator.
    • When a method returns a String, it is often necessary to determine what the String is for. If you know that the caller will concatenate the returned String, consider returning a StringBuffer instead, since this will return a reference to an object. A String creates a temporary object with a short lifetime.
    • Create as few temporary objects as possible; fewer objects means fewer GC operations.
    • Do not create objects in the nDraw method
  • Static is better than abstract
    • If you don’t need to access certain fields in a pair and just want to call some of its methods to perform a common function, you can make the method static and call it 15%-20% faster without having to create objects to call it. You don’t have to worry about changing the state of the object when you call this method (static methods can’t access non-static fields).
  • Use the static final modifier for constants
    • static int intVal = 42; static String strVal = “Hello, world!” ;
    • The compiler generates an initial method for the above code, called a method, which is called the first time the defined class is used. This method assigns the value of 42 to intVal and a reference from the string constant table to strVal. When the assignment is complete, we can access the specific value through field search.
    • Final to optimize:
    • static final int intVal = 42; static final String strVal = “Hello, world!” ;
    • In this way, you don’t need methods to define classes, because all constants are initialized in the initializer of the dex file. IntVal is called to point directly to the value of 42, while strVal is called in a relatively lightweight string constant rather than a field search.
    • This optimization only works for primitive data types and String constants, but not for constants of other data types.
  • Use primitive data types instead of encapsulated data types for no particular reason. Int is more efficient than Integer, as are other data types.
    • Arrays of primitive data types are also superior to arrays of object data types. Two other parallel arrays are more efficient than a wrapped array of objects. For example, arrays like Foo[] and Bar[] are much more efficient to use than arrays like Custom(Foo,Bar)[].

4.3 View exception optimization

  • View custom control exception destruction save state
    • It’s often overlooked, but in the pursuit of high-quality code, it’s also necessary. Take an example!

      @override protected Parcelable onSaveInstanceState() {// Save important information. //return super.onSaveInstanceState(); final Bundle bundle = new Bundle(); bundle.putInt("selectedPosition",selectedPosition); bundle.putInt("flingSpeed",mFlingSpeed); bundle.putInt("orientation",orientation); return bundle; } @Override protected void onRestoreInstanceState(Parcelable state) { if (state instanceof Bundle) { final Bundle bundle  = (Bundle) state; selectedPosition = bundle.getInt("selectedPosition",selectedPosition); mFlingSpeed = bundle.getInt("flingSpeed",mFlingSpeed); orientation = bundle.getInt("orientation",orientation); return; } super.onRestoreInstanceState(state); }Copy the code

4.4 Removing light yellow Warning Optimization

  • The light yellow warning will not cause a crash, but as a programmer should try to remove the light yellow warning, standardize the code

4.5 Reasonable use of collections

  • Use optimized data sets
    • Android provides a series of optimized data set utility classes, such as SparseArray, SparseBooleanArray, LongSparseArray, using these apis can make our programs more efficient. The HashMap utility class is relatively inefficient because it needs to provide an object entry for each key-value pair, and SparseArray avoids the time it takes to convert a primitive data type to an object data type.

4.6 Activity invisible optimization

  • Free memory when the Activity interface is not visible
    • When the user opens another application and our application interface is no longer visible, we should release all resources related to the interface. Override the Activity’s onTrimMemory() method and listen for the TRIM_MEMORY_UI_HIDDEN level in this method. Once triggered, the user has left the program, the resource can be freed.
  • When I saw this, I thought it was very novel, but I didn’t use it in detail. If that great god has a specific operation plan, I can share it.

4.7 Use Service sparingly

  • Use Service sparingly
    • If your application needs to use a Service to perform background tasks, you should only run the Service while the task is being executed. When a Service is started, the system tends to reserve the process on which the Service depends. The number of processes that the system can cache in the LRUcache decreases, which costs more performance during program switching. We can use IntentService, which automatically stops when the background task is finished, avoiding the memory leak of Service.

5. Network optimization

5.1 Picture Classification

  • Image network optimization
    • For example, I saw the Douban interface, which provides a way to load pictures is particularly good. There are three kinds of image data returned by the interface, one is the high definition large image, one is the normal image, and one is the thumbnail image. When the user is in wifi to set the control of high definition large picture, when 4g or 3G mode load normal picture, when the weak network conditions load thumbnail [also known as and loading picture].
    • In simple terms, according to the user’s current network quality to determine what quality of pictures to download (more e-commerce). Douban open source interface can refer to!

5.2 Obtaining Network Data optimization

  • Mobile access to network data optimization points
  • Connection multiplexing: saves the connection establishment time. For example, keep-alive is enabled.
    • By default for Android, keep-Alive is enabled for both HttpURLConnection and HttpClient. HttpURLConnection has a connection pool Bug before 2.2. For details, see: Android HttpURLConnection and HttpClient
  • Request merge: that is, multiple requests are combined into one request. CSS Image Sprites in web pages are more common. If there are too many requests on a page, you can also consider merging some requests.
  • Reduce the size of the requested data: For POST requests, the body can be gzip compressed, and the header can be compressed (HTTP only)
    • The body of the returned data can also be gzip compressed, reducing the size of the body data to about 30% of its original size. (The volume of key data of returned JSON data can also be considered, especially in the case of little change in returned data format, the data returned by Alipay chat is used)

5.3 Network Request Exception Interception Optimization

  • During the process of retrieving the data, errors may occur when accessing the interface and parsing the data, and we can intercept errors at these two layers with interceptors.

    • 1. When accessing the interface, we don’t have to set up interceptors because Retrofit automatically throws exceptions when errors occur. For example, common request exceptions are 404,500,503 and so on.
    • 2. When parsing data, we set an interceptor to determine whether the code in Result is successful. If not, we will throw the corresponding exception according to the error code agreed with the server. For example, token failure, disabling login of multiple devices with the same account, missing parameters, abnormal parameter transfer, etc.
    • 3. In addition, in order to avoid judging and processing errors in the View layer, we must also set an interceptor to intercept onError events and use ExceptionUtils to handle them separately according to the error type.
    • ExceptionUtils class in lib Very low intrusion, no need to change the previous code!
    @ Override public void onError (Throwable e) {/ / can be called directly ExceptionUtils handleException (e); }Copy the code

6. Thread optimization

6.1 Using thread Pools

  • Manage global threads with thread pools
    • Disadvantages of implementing the Runnable method by creating threads directly
      • The creation and destruction of a large number of threads can easily lead to frequent GC execution, resulting in memory jitter, and when memory jitter occurs, for mobile terminals, the biggest impact is to cause interface lag
      • Both thread creation and destruction take time, and when a large number of threads are created and destroyed, this time consumption becomes significant, resulting in a performance penalty
    • Why thread pools
      • Reusing threads in the thread pool to avoid the performance cost of frequently creating and destroying threads; Effectively control the maximum number of concurrent threads, prevent too many threads from preempting resources and causing system blocking; Threads can be managed to some extent.
    • The classic example of using thread pool management
      • RxJava, RxAndroid, the bottom of the thread pool encapsulation management is particularly worth reference
    • Thread pools, threads, multithreading
      • Reference: Lightweight thread pool wrapper library that supports asynchronous callbacks and can detect the status of thread execution
      • Where are new Threads used frequently in this project
        • Save images [note that it takes too long to save large and multi-image scenes]; Some pages query data from a database; Set the center to clear images, videos, downloaded files, logs, system cache and other cache content
        • Using a thread pool to manage library benefits such as saving images, placing time-consuming operations into child threads, and detecting execution start, exception, success, failure, and other states during processing.

7. Image optimization

7.1 bitmap optimization

  • How to calculate the size of memory used to load images
    • Load network images: bitmap memory size = image length x image width x number of bytes per pixel
    • Bitmap memory size = width * height * nTargetDensity/inDensity A pixel of memory. Be careful not to ignore the influence term Density
  • The first load picture optimization processing: compressed picture
    • Quality compression method: under the premise of maintaining the pixel to change the depth and transparency of the picture, to achieve the purpose of compression of the picture, so suitable for the transfer of binary picture data, such as sharing pictures, to pass binary data in the past, limited to 500KB.
    • Sampling rate compression method: If the inSampleSize value (int type) is set to n, the width and height of the inSampleSize value are 1/ N, and the width and height are reduced, and the memory is reduced.
    • Zoom compression: Android uses Matrix to scale, rotate, translate, tangent and other transformations of the image. Very powerful!
  • Second load image optimization: how to load hd images without compression?
    • BitmapRegionDecoder is used to display a rectangular area of an image. This class is ideal if you need to display a specific area of an image.

7.2 Glide loading optimization

  • Load the larger image in the gallery
    • If you slide very fast, glide load optimization is very important, the specific optimization method is shown below

      recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); If (newState == recyclerView.scroll_state_IDLE) {loggerUtils. e("initRecyclerView"+ "restore Glide load image "); Glide.with(ImageBrowseActivity.this).resumeRequests(); }else {loggerutils. e("initRecyclerView"+" disable Glide "); Glide.with(ImageBrowseActivity.this).pauseRequests(); }}});Copy the code

8. Load optimization

8.1 Lazy loading Optimization

  • This optimization is common in news apps
    • The combination of ViewPager+Fragment is also common in daily development and can be used to switch between displaying different types of pages.
    • Lazy loading, also known as lazy loading, is when the UI of the page is presented to the user and then loads the data of the page (from the network, database, etc.), rather than relying on the ViewPager preloading mechanism to load the data of two, three or more pages in advance. This improves the initialization speed of the owning Activity and saves traffic for users. This lazy loading approach has/is being adopted by many apps.
  • Look at this article for details
    • www.jianshu.com/p/cf1f4104d…

8.2 Startup page optimization

  • Startup time analysis
    • The system creates the process and the application starts the process, the former is done by the system itself, it’s usually very fast, we can’t interfere, I think what we can do is optimize the application starts, This is the time between the onCreate() execution of the Application and the end of the onCreate() execution of the MainActivity.
  • Startup time optimization
    • Application’s onCreate() method
    • MainActivity’s onCreate() method
    • There are no more than three methods of optimization, as follows:
      • Lazy initialization
      • Background tasks
      • The interface is preloaded
  • Startup page white screen optimization
    • Why is this a problem?
      • When the system starts an APP, the Zygote process will first create a new process to run the APP, but the process creation is time, before the creation is complete, the interface is in a state of suspended animation, so the system will display a white or black screen depending on the theme color of your manifest file. The black (and white) screen is officially called a Preview Window.
      • This is actually caused by the activity’s default theme android:windowBackground being white or black.
      • In summary, the launch sequence is: App start — Preview Window(also known as Preview Window) — start page
    • The solution
      • Add a background style to the current launch page, and then SplashActivity references the current theme. Note that the window’s background is set to empty on this page!
      • For more information on why the startup screen is blank and there are different solutions, you can check out my blog: Optimizing the startup page of your App
  • Startup time optimization
    • IntentService child threads share some of the initialization work
      • Now the application initialization content includes: Ali cloud push initialization, Tencent Bugly initialization, IM initialization, Shenze initialization, memory leak tool initialization, toutiao adaptation program initialization, Ali cloud hot repair…… And so on. Putting some of the logic into IntentService can save a lot of time.
      • To reduce application initialization time, start the IntentSerVice thread and place some logical and time-consuming initialization operations there
      • IntentService source code analysis: IntentService source code analysis

9. Other optimizations

9.1 Static Variable Optimization

  • Try not to use static variables to store core data. Why is that? – This is because Android processes are not safe, and process-level variables, including application objects and static variables, do not stay in memory because they can be killed. – App does not actually restart after being killed. The Android system creates a new Application object and starts the activity from the last time the user left to create the illusion that the app was never killed. In this case, static variables and other data are initialized because the process has been killed, so it is not recommended to store static variables (including global data static data in Application).

9.2 Annotations instead of enumerations

  • Use annotations to qualify the incoming type

    • For example, especially when writing third-party open source libraries, it may be necessary to restrict incoming types for some methods that are exposed to developers. Here’s an example:

    • The original code

      /** * Set the player type, must be set * Note: Thanks for someone's suggestion, this limits the incoming value type * input value: @param playerType IjkPlayer or MediaPlayer. */ public void setPlayerType(int playerType) {mPlayerType = playerType; }Copy the code
    • Optimized code, effectively avoid the first way the developer passed in the value error

      /** * Set the player type, must be set * Note: Thanks for someone's suggestion, this limits the incoming value type * input value: ConstantKeys. IjkPlayerType. TYPE_IJK or ConstantKeys. IjkPlayerType. TYPE_NATIVE * @ param playerType IjkPlayer or MediaPlayer. */ public void setPlayerType(@ConstantKeys.PlayerType int playerType) { mPlayerType = playerType; } /** * Define type * TYPE_IJK IjkPlayer, based on IjkPlayer * TYPE_NATIVE MediaPlayer, */ @retention (retentionPolicy.source) public @interface IjkPlayerType {int TYPE_IJK = 111; int TYPE_NATIVE = 222; } @IntDef({IjkPlayerType.TYPE_IJK,IjkPlayerType.TYPE_NATIVE}) public @interface PlayerType{}Copy the code
  • Use annotations instead of enumerations, as shown below

    @Retention(RetentionPolicy.SOURCE)
    public @interface ViewStateType {
        int HAVE_DATA = 1;
        int EMPTY_DATA = 2;
        int ERROR_DATA = 3;
        int ERROR_NETWORK = 4;
    }
    
    Copy the code

9.3 Optimization of multi-channel packaging

  • Still packing by hand? Try python automated packaging…
    • Wall · E multichannel package Python script test tool. With this automated script, you can run a script or run a script from the command line to achieve multichannel package. The configuration information is very simple and the code has been commented in detail. You can customize the output file path and modify the multi-channel configuration information, which is simple and practical. Project address: github.com/yangchong21…

9.4 TrimMemory and LowMemory optimization

  • What can be optimized?
    • In the onTrimMemory() callback, there are several states in which non-important memory resources should be cleaned up. For these caches, as long as read into memory, such as the most common image cache, file cache, etc. For image cache, the market, the picture of the conventional load library, in general are three levels of cache, so tight in the memory, we should first clean up this part of the image cache, after all the picture is for memory, and when I come back again, although the memory of resources by recycling off, still can restore it from the disk or network.
  • The general idea is as follows
    • In lowMemory, call Glide. CleanMemory () to clean up all memory cache.
    • Call Glide. CleanMemory () to clean up all the memory cache when the App is replaced in the background.
    • In other cases of the onTrimMemory() callback, the Glide.trimMemory() method is called directly to Glide to handle the memory condition.

9.5 Optimization of polling Operation

  • What is rotation training request?
    • The simple understanding is that the App end repeated requests at certain intervals is called the rotation request, for example: the App end reported positioning information at intervals, the App end pulled the user status at intervals, etc., these should be the rotation request. For example, e-commerce projects, a lottery page, every 1 minute to call the interface, pop up some winners information, you should have seen this kind of polling operation at some stage!
  • Specific optimization operation
    • Long connection is not stable and reliable, and carry out training in rotation operations are generally more stable network request, and training in rotation operations are generally have a life cycle, which in a certain life cycle training in rotation operation, and long connection are generally the life cycle of the whole process, so in this respect is not suitable.
    • It is recommended to do polling operation in service, polling request interface, specific practices and points to note, you can directly see the project code. Look at the LoopRequestService class in the app package.
    • Initialize the TimerTask when the user opens the page, request the server to pull the order information and update the UI once every minute, and clear the TimerTask when the user leaves the page, i.e. cancel the rotation request operation.

9.6 Optimization for removing duplicate dependencies

  • I’m sure you’re wondering, there are a lot of blogs on the web about this. But I’m here to say, how do YOU find all the dependency trees for your project

    • Note: app is the project mudule name. Normally it’s app!
    gradlew app:dependencies
    
    Copy the code
  • The structure of the dependency tree is shown below, leaving out a lot of code

    | | | | | | \ - android. The arch core: common: 1.1.1 (*) | | | | \ - com android. Support: support - annotations: 26.1.0 - > 28.0.0 | + -- -- -- com. Journeyapps: zxing - android - embedded: 3.6.0 | | + -- -- -- com. Google. Zxing: core: 3.3.2 rainfall distribution on 10-12 | | \ -- -- -- Com. Android. Support: support - v4:25.3.1 | | + -- -- -- com. Android. Support: support - compat: 25.3.1 - > 28.0.0 (*) | | + -- -- -- Com. Android. Support: support - media - compat: 25.3.1 | | | + -- -- -- com. Android. Support: support - annotations: 25.3.1 - > 28.0.0 | | | \ - com. Android. Support: support - compat: 25.3.1 - > 28.0.0 (*) | | + -- -- -- com. Android. Support: support - core - utils: 25.3.1 - > 28.0.0 (*) | | + -- -- -- com. Android. Support: support - core - UI: 25.3.1 - > 28.0.0 (*) | | \ -- -- -- Com. Android. Support: support - fragments: 25.3.1 - > 28.0.0 (*) \ - com android. Support: multidex: 1.0.2 - > 1.0.3Copy the code
  • Then look at which duplicate jars

    • [image upload failed…(image-b9d450-1563928824510)]

  • Then modify the Gradle configuration code

    api (rootProject.ext.dependencies["zxing"]){
        exclude module: 'support-v4'
        exclude module: 'appcompat-v7'
    }
    
    Copy the code

9.7 Four types of reference optimization

  • Soft reference usage scenarios

    • Normal is used to deal with large images such as large memory

      • The code is shown below
      Bitmap bitmap = bitmaps.get(position); BitmapSoftReference = new SoftReference<>(bitmap); if(bitmapSoftReference.get() ! = null) { viewHolder.imageView.setImageBitmap(bitmapSoftReference.get()); } // See glide bottom source code, also do the relevant soft reference operationCopy the code
    • This uses the soft reference benefit

      • The strong reference of the bitmap object instance is obtained through the get() method of the soft reference, and it is found that the object is not reclaimed. When the GC is out of memory, it does not reclaim soft reference objects. The view’s background is now displayed
      • In reality, we get a lot of images. And then you might show a bunch of views, and in this case it’s easy to run out of memory and get oom, run out of memory and start GC. After the GC, bitmapsoftreference.get () returns null instead of a bitmap object. In this case, the background image is not displayed, indicating that the soft reference is reclaimed when the system memory is insufficient.
      • After soft reference is used, the memory space of these cached image resources can be freed before OutOfMemory exception occurs, thus avoiding the memory limit and avoiding Crash.
  • Weak reference usage scenarios

    • Weak references – > can be collected by the garbage collector at any time, not necessarily when the virtual machine is running out of memory.
    • For infrequently used objects, you need to reclaim them as soon as possible. Using weak references can ensure that the memory is reclaimed by the VM. For example, handler, if you want to recycle as quickly as possible after using it, look at the following code
    private MyHandler handler = new MyHandler(this);
    private static class MyHandler extends Handler{
        WeakReference<FirstActivity> weakReference;
        MyHandler(FirstActivity activity) {
            weakReference = new WeakReference<>(activity);
        }
    
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what){
            }
        }
    }
    
    Copy the code
  • When do you use soft references and when do you use weak references?

    • Personally, if you just want to avoid OutOfMemory exceptions, you can use soft references. If you are more concerned about the performance of your application and want to reclaim some memory-consuming objects as quickly as possible, you can use weak references.
    • It can also be judged by how often an object is used. If the object is likely to be used frequently, use soft references. If it is more likely that the object will not be used, use weak references.

9.8 Loading Loading Optimization

  • There are at least two kinds of loading in real development
    • The first type is loading loading from page A to page B. In this case, the page is pure white when loading is displayed, and the content page is displayed only after loading data.
    • The second is to operate some logic on a page, such as some time-consuming operations. In this case, it is partially loading[usually using one-frame animation or tween animation]. Due to frequent use, it is recommended to add the operation of destroying animation when destroying popovers.
  • Custom loading
    • Github.com/yangchong21…

9.9 Object Pool Optimization

  • Object Pools optimizations frequently create and destroy objects
  • Object pooling prevents memory jitter caused by frequent object creation and destruction
    • At some point, we need to make frequent use of temporary objects, and if we apply for new resources every time we use them, it is likely to cause frequent GC and affect the flow of the application. In this case, if the object has a clear life cycle, then you can define a pool of objects to achieve efficient reuse of objects.
    • For specific examples, see the project: github.com/yangchong21…

10. RecyclerView optimization

10.1 Why is the page stuck

  • RecyclerView sliding stuck what are the reasons?
    • First: nested layout sliding conflicts
      • The key reason nested slides are difficult to handle is that when the child controls consume the event, the parent controls no longer have a chance to handle the event, so once the inner slider consumes the slide, the outer slider never has a chance to respond to the slide
    • Second: nested layout level is too deep, such as six or seven layers
      • Measuring, drawing layouts can cause slippage
    • The third kind: for example, use RecyclerView to realize the gallery, load relatively large pictures, if you slide quickly, there may be stuck, mainly load pictures need time
    • 4. A time consuming operation in onCreateViewHolder or onBindViewHolder causes a delay. The onCreateViewHolder() and onBindViewHolder() methods in RecyclerView.Adapter are both time-sensitive. Time-consuming operations such as I/O reading and writing and Bitmap decoding are best avoided in them.
  • About RecyclerView packaging library
    • Github.com/yangchong21…

10.2 Specific optimization plan

  • 03. Alternative SparseArray HashMap
  • 04. Waterfall flow picture confusion resolved
  • 05. Where is the item click event optimized
  • 6. The ViewHolder optimization
  • 07. More optimization for continuous pull-up loading
  • 08. Drag and drop sort and slide delete optimization
  • 09. Pause or stop loading data optimizations
  • 11. Save the status in abnormal cases
  • 12. Insert data optimization under multi-threading
  • RecyclerView optimization treatment
  • 15. Adapter optimization
  • See this blog: recyclerView optimization

Friendly recommendation: Android dry goods to share

At this point, this has ended, if there is wrong place, welcome your suggestion and correction. Meanwhile, I look forward to your attention. Thank you for reading. Thank you!