The main content

Android Studio supports six types of Android Lint rules, this article mainly describes the 32 items included in Performance, the main content is the document translation, appropriate to add some of my own thoughts.

Classification details

Efficient use of resources

UnusedIds

Unused resource ids are defined in the Layout file as resource ids that are never used, but sometimes they make layout easier to read without the need to remove unused resource ids.

Overdraw

Overdraw: a drawn region is drawn more than once.

If you set a background for a root view, you need to set a theme with background=null. Otherwise, the background of the theme will be drawn first and then the background will be drawn completely overwriting the theme. Background. This is overdrawing.

The detector relies on scanning Java code to figure out which layout files are associated with which activities, and currently uses an imprecise pattern matching algorithm. As a result, false reminders can be given by incorrectly inferring the layout’s association with activities.

If you want to apply a background image to multiple pages, consider customizing the theme and setting the background image inside the theme. Set the theme in layout instead of setting the background. If the background image has a transparent part and you want it and the theme to have a cascading effect, you can choose to merge the two backgrounds into a single image and then define the theme.

VectorPath

Android Studio allows you to create drawable images that are drawn using SVG.

UselessLeaf

The Layout without any View or background is redundant and can be removed. Make the interface more flat, more efficient nesting.

UselessParent

If a Layout that contains views does not have sibling layouts, and its external ViewGroup is not ScrollView or root, the Layout can be removed so that the View is included in its parent Layout. Make the interface more flat, more efficient nesting.

TooDeepLayout

If the Layout is too deeply nested, the performance will be affected. Use a tiled Layout instead. The default deepest View nesting is 10 layers, which can also be set using the environment variable ANDROID_LINT_MAX_DEPTH. System.getenv(“ANDROID_LINT_MAX_DEPTH”); Statement fetch, how to set has not been found.

TooManyViews

Too many Views in a Layout: Having too many Views in a Layout file can affect performance. Consider using composite drawables or other techniques to reduce the number of views in this layout. The default maximum number is 80, which can be set using the environment variable ANDROID_LINT_MAX_VIEW_COUNT. Getenv (“ANDROID_LINT_MAX_DEPTH”); Statement fetch, how to set has not been found.

NestedWeights

Weight nesting: Using a layout with a non-zero Weight value, the layout needs to be measured twice. If a LinearLayout containing a non-zero value is nested inside another LinearLayout containing a non-zero value, the number of measurements increases exponentially.

DuplicateDivider

This is mainly about RecyclerView divider, com. Android. Support: RecyclerView – v7 provides a class DividerItemDecoration set the line style, not included in this class in the earlier version, So after updating to a new version, you can use this class to reset the splitter line. Specific use, refer to the article: Android RecyclerView use full analysis

MergeRootFrame

When FrameLayout is root in a layout file and does not use attributes such as background or padding, it is often more efficient to use a merge tag instead of FrameLayout. But this depends on the Settings below, so make sure you understand how the Merge tag works before replacing it.

UnusedResources

Unused resources: Multiple refers to resources of type Drawable. Extra drawable resources make your APP bigger and the compilation process longer.

InefficientWeight

When the LinearLayout has only one Widget and uses Android :layout_weight, define the corresponding width/height to 0dp and the Widget will automatically fill up the remaining space. This is more efficient because you don’t have to calculate your size beforehand.

Efficient setup

DisableBaselineAlignment

When using LinearLayout to implement space segmentation to scale, the LinearLayout space is divided among several layouts with the layout_weight attribute. You should set is divided LinearLayoutbaseLineAligned = “false”, so that we can speed up the break up a space operations.

LogConditional

LogConditional: Use Android.util. Log to print DEBUG logs. This is usually only used in DEBUG mode. You do not need to print DEBUG logs at release. BuildConfig provides two one-debug constants to indicate whether or not we are in DEBUG mode. We can wrap DEBUG log statements with if(buildconfig.debug){} so that the compiler will remove these statements when it builds the release package. If you really need to print debug logs in release mode, you can use the @SuppressLint(“LogConditional”) annotation to tell the compiler to keep these logs in the release package.

UnpackedNativeCode

APP using System. LoadLibrary () loading Native library, android 6.0 or newer versions in the Manifest file application tag to add attribute android: extractNativeLibs = “false”, This speeds up the commit load and reduces the amount of storage your APP takes up.

More efficient alternatives

FloatMath

Do not use the FloatMath class for Math calculations. The Math class is recommended.

Earlier versions of Android recommended using FloatMath instead of the Math class because of floating-point performance. As hardware and systems evolve, this problem has gone away, and even jIT-optimized Math classes are faster than FloatMath, so you can use the Math class instead of FloatMath on Android F or later.

UseValueOf

When some classes construct new objects, it is recommended to use the factory method instead of the new keyword to declare new objects. For example, new Intger(0) can be replaced with integer.valueof (0). The factory method uses less memory because it uses the same instance for objects with equal values.

ViewHolder

When implementing adapters for lists such as ListView or GradView, you cannot inflate a new layout every time a getView call is made. If a reusable View object is given in the interface parameters, you can use that object instead of regenerating it. This should be very familiar, very simple and basic.

UseSparseArrays

A HashMap with a Key of type Integer can be replaced with SparseArray for better performance. Alternatives to HashMap are SparseBooleanArray, SparseIntArray, SparseLongArray, and the generic SparseArray class, each of which represents the type of Value. If HashMap must be implemented in some cases, you can SuppressLint checking with the @suppresslint annotation.

WakelockTimeout

Here’s a blog post about using Week Lock: Wakelock for Android Power Analysis

UseCompoundDrawables

When you have a display-only ImageView around a TextView, it is recommended to compound the ImageView and use drawables: DrawableTop, drawableLeft, drawableRight, drawableBottom, drawablePadding

A reminder of the spill

Recycle

Missing recycle() calls: Many resources such as TypedArrays, VelocityTrackers need to call the Recycle () method to reclaim the resource after they’ve been used.

ViewTag

Prior to version 4.0, the implementation of View.settag (int, Object) stored the Object in a static map and used strong references. This means that if the Object contains a reference to the Context Object, the Context is leaked.

Passing a View as an argument provides a reference to the Context in which it was created. Similarly, if you take View holders, you’ll also have a Context associated with that View.

HandlerLeak

Handler reference leak: Declaring a subclass of Handler such as MyHandler as an inner class prevents unwanted external objects from being garbage collected if the MyHandler object is associated with looper.getMainLooper () or looper.getMainLooper ().getQueue(). Cause a leak. This problem does not occur if the association corresponds to the main thread.

To cope, declare MyHandler as a static internal class and hold an external class object in the way of WeakReference. MyHandler uses this object to operate the attributes and methods of the external class.

DrawAllocation

Memory allocation during drawing: Avoid allocating memory to new objects during layout drawing. Because these operations are called frequently, frequently allocating memory can evoke garbage collection, interrupt UI drawing, and cause stuttering.

StaticFieldLeak

A non-static inner class has an implicit reference to its outer class object.

If the external class Fragment or Activity, this reference means that the long-running handler/loader/task will hold a reference to the external class object, preventing it from being recycled.

Similarly, direct references to fragments or activities by long-running handlers/loaders/tasks can cause leaks.

The ViewModel class should prohibit references to View or non-Application Context objects.

Code to remind

AnimatorKeep

Properties Animation supports properties by default as listed below. If you go beyond these ranges, a locally defined function is called through reflection. Declare a property animation object for example: The “rotation” in objectAnimator. ofFloat(view, “Rotation “, 0, 360) is the property to operate on. If the property is not in the following list such as objectAnimator.offloat (View, “position”, 0, 360), a corresponding method setPosition(float position) needs to be defined locally, And this method needs to be annotated with @keep to prevent it from being cleaned up as a useless method.

    static {
        PROXY_PROPERTIES.put("alpha", PreHoneycombCompat.ALPHA);
        PROXY_PROPERTIES.put("pivotX", PreHoneycombCompat.PIVOT_X);
        PROXY_PROPERTIES.put("pivotY", PreHoneycombCompat.PIVOT_Y);
        PROXY_PROPERTIES.put("translationX", PreHoneycombCompat.TRANSLATION_X);
        PROXY_PROPERTIES.put("translationY", PreHoneycombCompat.TRANSLATION_Y);
        PROXY_PROPERTIES.put("rotation", PreHoneycombCompat.ROTATION);
        PROXY_PROPERTIES.put("rotationX", PreHoneycombCompat.ROTATION_X);
        PROXY_PROPERTIES.put("rotationY", PreHoneycombCompat.ROTATION_Y);
        PROXY_PROPERTIES.put("scaleX", PreHoneycombCompat.SCALE_X);
        PROXY_PROPERTIES.put("scaleY", PreHoneycombCompat.SCALE_Y);
        PROXY_PROPERTIES.put("scrollX", PreHoneycombCompat.SCROLL_X);
        PROXY_PROPERTIES.put("scrollY", PreHoneycombCompat.SCROLL_Y);
        PROXY_PROPERTIES.put("x", PreHoneycombCompat.X);
        PROXY_PROPERTIES.put("y", PreHoneycombCompat.Y);
    }
Copy the code
ObsoleteSdkInt

Useless SDK version checking: The Android SDK version updates quickly, and many API uses require checking the SDK version to prevent crashes like Not Found. Increasing the value of minSdkVersion during APP iterations will result in some SDK version checks not being needed.

This SDK version check leads to unnecessary resource searches.

DevModeObsolete

Previously, the documentation suggested creating a Dev Product in productFlavors. Set up minSdkVersion 21 to enable Multidexing during development to speed up the build process. You don’t need to do this anymore. Newer ides and Gradle plug-ins automatically recognize the API level of the connected device. Multindexing will be turned on if the linked device API level is 21 or higher, just as dev Product was set.

For details, see Enable Android MultiDex

ObsoleteLayoutParam

Useless LayoutParam: This prompt is generated when a Widget is given a LayouParam that is not provided by the Layout. This occurs when a Layout type is changed without changing the LayoutParam Settings of an internal Widget or copying a Widget from one Layout into a different Layout type.

This useless LayoutParam causes invalid property resolution at run time and is misleading to those reading the code. So these useless attributes should be removed.

other

WearableBindListener
UseOfBundledGooglePlayServices