It has been more than a year since I joined the company in July last year (2018/7/13) and now (2019/8/15). In this year, I have learned a lot from being a rookie. I have recorded the code optimization and performance optimization experience in the development process, which is convenient for others to avoid detour.

Performance optimization

1. Memory consumption caused by packing

Boolean isShow =new Boolean(true);Copy the code

The above code causes the following problems:

//boolean
Boolean isShow =Boolean.TRUE ;

//integer
Integer i= 2;

Copy the code

SharedPreferences uses commit to block threads

                final SharedPreferences.Editor edit = settings.edit();
                edit.putBoolean(TIPS, true);
                edit.commit();
Copy the code

The above code causes the following problems:

Error location of selector item

error

<?xml version="1.0" encoding="utf-8"? >
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:drawable="@drawable/normal" />
    <item android:drawable="@drawable/pressed" android:state_pressed="true"/>

</selector>
Copy the code

The selector above causes the following problem

<?xml version="1.0" encoding="utf-8"? >
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:drawable="@drawable/pressed" android:state_pressed="true"/>
    <item android:drawable="@drawable/normal" />

</selector>
Copy the code

If none of the previous items match, the last item will be selected.

Memory leak caused by context

public static WifiManager getWIFIManager(Context ctx) {
	WifiManager wm = (WifiManager) ctx.getSystemService(Context.WIFI_SERVICE);
}
Copy the code

The above code directly uses the context to get the system’s WiFi service, causing the following problems

public static WifiManager getWIFIManager(Context ctx) {
	WifiManager wm = (WifiManager) ctx.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
	}
Copy the code

Why not use the activity context instead of the application context? Since the context life cycle of an activity is the same as that of an activity, the context should also be released when the activity is released. In this case, because the context is held by wifiManager, the activity cannot be released, resulting in a memory leak. The context life cycle of an application is consistent with the application life cycle. So when retrieving resources that are not related to the current activity lifecycle but related to the entire application lifecycle, use the application context.

public Context getApplicationContext (a)
/*Return the context of the single, global Application object of the current process. This generally should only be used if you need a Context whose lifecycle is separate from the current context, that is tied to the lifetime of the process rather than the current component.
*/
Copy the code

5. Use SparseArray instead of HashMap

In Android, SparseArray can be used to replace HashMap if the key in <key,value> is the basic data type: int, Long, etc., to avoid memory consumption caused by automatic packing and entry in HashMap. There are several types of <key,value> that can be replaced by SparseArray:

SparseArray          <Integer, Object>
SparseBooleanArray   <Integer, Boolean>
SparseIntArray       <Integer, Integer>
SparseLongArray      <Integer, Long>
LongSparseArray      <Long, Object>
LongSparseLongArray  <Long, Long>   //this is not a public class  
Copy the code

Compare SparseIntArray with HashMap<Integer, Integer> as follows: SparseIntArray

SparseIntArray

class SparseIntArray {
    int[] keys;
    int[] values;
    int size;
}
Copy the code

Class = 12 + 3 * 4 = 24 bytes Array = 20 + 1000 * 4 = 4024 bytes Total = 8,072 bytes

HashMap

class HashMap<K.V> {
    Entry<K, V>[] table;
    Entry<K, V> forNull;
    int size;
    int modCount;
    int threshold;
    Set<K> keys
    Set<Entry<K, V>> entries;
    Collection<V> values;
}
Copy the code

Class = 12 + 8 x 4 = 48 bytes Entry = 32 + 16 + 16 = 64 bytes Array = 20 + 1000 x 64 = 64024 bytes Total = 64,136 bytes As you can see, HashMap takes up almost eight times as much memory as SparseIntArray for the same elements.

The disadvantage of SparseIntArray

SparseIntArray uses binary lookup to find keys, so it can’t find an element as fast as a Hashmap. Therefore, SparseIntArray can be used when the amount of data is small, but hashMap can be used when the amount of data is very large, resulting in higher search speed.

6, custom view in layout, draw, onMeasue in the new object

The problem code

pubic class myview extends View
{

    public myview(Context context) {
        super(context);
    }
    @Override
    protected void onDraw(Canvas canvas)
    {
        super.onDraw(canvas);
        int x=80;
        int y=80;
        int radius=40;
        Paint paint=new Paint();
        // Use Color.parseColor to define HTML colors
        paint.setColor(Color.parseColor("#CD5C5C")); canvas.drawCircle(x,x, radius, paint); }}Copy the code

The onLayout,onDraw, and onMeasue methods are often overridden for custom views, but be aware that new objects in these methods have the following problems

Optimize the code

public class myview extends View
{
		int x;
        int y;
        intradius; Paint Paint.public myview(Context context) {
        super(context);
        init();
    }
    @Override
    protected void onDraw(Canvas canvas)
    {
        super.onDraw(canvas);
        // Use Color.parseColor to define HTML colors
        paint.setColor(Color.parseColor("#CD5C5C"));
        canvas.drawCircle(x,x, radius, paint);
    }
	private voidInit () {x=80;
        y=80;
        radius=40;
        paint=newPaint(); }}Copy the code

The onLayout,onDraw, and onMeasue methods cannot be used to execute new objects and initialize them.

Creating objects ahead of time is an important optimization. Views are redrawn very frequently, and many drawing objects require expensive initialization. Creating drawing objects within your onDraw() method significantly reduces performance and can make your UI appear sluggish.

To summarize, it is best to initialize and new objects in advance when customizing a view, because onDraw, onMeasure, and onLayout methods are called frequently. If you initialize and new objects in this view, frequent GC operations will seriously affect performance and may cause frame drop.

Ondraw is called when the view is initialized. 2. When the view’s invalidate() method is called. When is the invalidate() method called? The onDraw method is called when the view state needs to change, such as when botton is clicked, editText is typed, etc.

Memory leaks caused by static variables

The problem code

public class MyDlg extends Dialog {
   
    private View mDialog;
    private static MyDlg sInstance;
    public MyDlg(Context context) {
        super(context);
        sInstance = this;
        init();
    }
    private void init(a) {
        mDialog = LayoutInflater.from(mCtx).inflate(R.layout.dialog_app_praise, null);
        setContentView(mDialog);
  }       
Copy the code

The above code causes the following problems:

8. Overdraw problem

The problem code

<?xml version="1.0" encoding="UTF-8"? >
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical"
    android:background="@drawable/layout_content_bkg" >

	<include layout="@layout/title_bar" />
	
	<ScrollView 
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="12dip"
        android:scrollbars="vertical" >
		
		<LinearLayout
			android:layout_width="fill_parent"
			android:layout_height="wrap_content"
			android:orientation="vertical"
			android:background="@drawable/layout_content_bkg"
			android:layout_marginTop="14dip"
			android:paddingLeft="13dip"
	   	 	android:paddingRight="13dip" >.</LinearLayout>
	</ScrollView>
</LinearLayout>
Copy the code

The background of the linearLayout in the above code is the same as the background in the ScrollView. You just need to keep the background in the parent LinearLayout, otherwise you will draw more than once, which will cause the overdraw problem.

9. Inefficent Layout weight

The problem code

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="48dp"
        android:layout_gravity="bottom"
        android:background="@color/white"
        android:gravity="center_vertical"
        android:orientation="horizontal"
        >

    <TextView
        android:layout_weight="1"
        android:id="@+id/text"
        android:layout_width="165dp"
        android:layout_height="wrap_content"
        android:layout_marginLeft="15dp"
        android:textSize="15sp" />

    <android.support.v7.widget.SwitchCompat
        android:checked="true"
        android:id="@+id/0checkbox"
        android:layout_width="wrap_content"
        android:layout_height="36dp"
        android:layout_marginEnd="15dp" />
    </LinearLayout>
Copy the code

Textview layout_weight=”1″. Textview layout_width=”165dp”. This brings up the following questions

10, string operation optimization

String text="bitch";/ / 1
StringBuilder.append(" fuck " + text);
/ / 2
mStringBuilder.append(" fuck ").append(text);
Copy the code

Which code, 1 or 2, performs better? The second method performs better. The first method creates a new “fuck” +text string and appends it to StringBuilder, while the second method does not create a new string, so it performs better.

Code optimization

1, Eliminate redundant “collection.addall ()”

Original code:

        ArrayList<BaseFile> lists = null;
        if(getImages() ! =null) {
            lists = new ArrayList<>();
            lists .addAll(getImages());
        }
Copy the code

Optimized code:

        ArrayList<BaseFile> lists = null;
        if(getImages() ! =null) {
            lists = new ArrayList<>(getImages());
        }
Copy the code

2. Use the array copy method

Original code:

        for(int i=0; i<ITEM_SIZE; i++){ mContentsArray[i] = contents[i]; }Copy the code

Optimized code:

System.arraycopy(contents, 0, mContentsArray, 0, ITEM_SIZE);
Copy the code

reference

1, stackoverflow.com/questions/5…

2, stackoverflow.com/questions/4…

3 developer.android.com/reference/a…

4, stackoverflow.com/questions/2…

5, developer.android.com/training/cu… 6, stackoverflow.com/questions/1…