Wang Gang ---- memory optimization performance optimization (ii) optimize memory memory jitter and good coding practice

First: the jitter memory
1, memory jitter reasons: (recovery rate when dispensing speed is greater than) the frequent memory allocation and recovery, will eventually produce OOM.
(1) We look for a memory jitter code, open up a two-dimensional array, frequent string concatenation.

 public void imPrettySureSortingIsFree() {
        int dimension = 300;
        int[][] lotsOfInts = new int[dimension][dimension];
        Random randomGenerator = new Random();
        for (int i = 0; i < lotsOfInts.length; i++) {
            for (int j = 0; j < lotsOfInts[i].length; j++) {
                lotsOfInts[i][j] = randomGenerator.nextInt();
            }
        }

        for (int i = 0; i < lotsOfInts.length; i++) {
            String rowAsStr = "";
            //排序
            int[] sorted = getSorted(lotsOfInts[i]);
            //拼接打印
            for (int j = 0; j < lotsOfInts[i].length; j++) {
                rowAsStr += sorted[j];
                if (j < (lotsOfInts[i].length - 1)) {
                    rowAsStr += ", ";
                }
            }
            Log.i("ricky", "Row " + i + ": " + rowAsStr);
        }
    }
    

When a string concatenation also clone operation. Clones will continue to produce the object memory block.

 public int[] getSorted(int[] input){
            int[] clone = input.clone();
            Arrays.sort(clone);
            return clone;
        }

Click the profile run, this time we mainly see Allocations (a certain period of time to open up the number of memory objects) and Deallocations (a certain period of time the number of recovered memory) two fields.
Run profile, you will find the gc (garbage collection image) icon appears frequently.
Workaround: Use StringBuffer StringBuilder
memory jitter (2) WebView caused

 WebView webView = (WebView) findViewById(R.id.webview);
        webView.getSettings().setUseWideViewPort(true);
        webView.getSettings().setLoadWithOverviewMode(true);
        webView.loadUrl("file:///android_asset/shiver_me_timbers.gif");

Solution: Turn the independence process. Open a separate process running the current Activity. In the file list, locate the Activity, adding the process ID.

 <activity android:name=".CachingActivity" android:process=":P"/>

Recommendations written WebView's Activity open a separate process. We open the QQ micro letter Jingdong, you will find they have a lot of processes, the reason is because the WebView.

2, collection algorithm:
sub-band mobile phone Algorithms
II: good coding habits optimize memory
1, data types: Do not use basic data types accounted for more space than demand. For example, use int Do not use long, can not use decimal integer.
2, as far as possible with the foreach loop, less Iterator, minimize the use of automatic packing
solutions of the process 3. Data structures and algorithms;
(1) into a recursive algorithm for loop
(2) minimize the use of the HashMap, the amount of data within one thousand Sparse arrays may be used (key is an integer), ArrayMap (key object) but save memory performance than HashMap. Time for space.
Sparse integer as the key, there is no problem of packing. ArrayMap key for the object.
4 Enumeration Optimization:
This is a enumeration code

public enum SHAPE{
    RECTANGLE,
    TRIANGLE,
    SQUARE,
    CIRCLE
}

There are four values, it will open up four objects in memory. Consumption is relatively large for memory
modification is

package com.example.wuyang.lsn4code;

import android.support.annotation.IntDef;
import android.support.annotation.StringDef;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

public class SHAPE {
    public static final int RECTANGLE=0;
    public static final int TRIANGLE=1;
    public static final int SQUARE=2;
    public static final int CIRCLE=3;

    //flag的真和假表示将来取的数据可以用或(|)来输入;比如这种形式RECTANGLE|TRIANGLE
	//value表示可选值,只允许我们定义的四个值
    @IntDef(flag=true,value={RECTANGLE,TRIANGLE,SQUARE,CIRCLE})
	//注解允许用在什么地方,我们这里允许写在参数,方法,成员变量
    @Target({ElementType.PARAMETER,ElementType.METHOD,ElementType.FIELD})
	//注解的存活时间;编译阶段存在就行。
    @Retention(RetentionPolicy.SOURCE)
    public @interface Model{

    }
   
	//只有赋予我们规定的四个值
    private @Model int value=RECTANGLE;
	//限制用户传入的参数
    public void setShape(@Model int value){
        this.value=value;
    }
    @Model
    public int getShape(){
        return this.value;
    }
}

This opens up an object on it.
In use in MainActivity

 SHAPE s=new SHAPE();
 //因为flag=true,所以这里可以输入两个值
       s.setShape(SHAPE.CIRCLE|SHAPE.RECTANGLE);
       System.out.println(s.getShape());

5.static of problems with static final.
static invoked by the compiler clinit method to initialize
static final work does not need to be initialized, packaging can be called directly in dex file, and does not apply in the class initialization memory. Therefore, members of the basic data types, can be written as a full static final
connect string 6. minimize the use of the plus (+)
7. Repeat application memory problems
(1) multiple invocations of the same methods, such as recursive function, the callback function Do new objects,
(2) reading cycle directly in the new stream objects. Do not recycle new objects likely to cause memory jitter.
(3) Do not onMeause () onLayout () onDraw ( ) to refresh the UI (such as requestLayout, Invalidate), which resulted in calls itself.
8. Avoid GC to be recovered in the future to be reused
, such as ListView optimization is this.
Solution: Memory design mode object pool + LRU algorithm
we are here to write an object pool, the constant reuse something. Here we write a class, after the reader if I need to object pool can override this class.

	/**
	 *首先,在freePool中我们初始化2(initialCapacity)个对象,这时候来了个用户,需要用我对象池中的对象。
	 *就在freePool中申请一个对象,并且把这个申请到的对象放到lentPool中,这时候用户使用
	 *的,就是lentPool中的这个对象。第二个用户来用,就重复第一个用户的操作。接下来来第三个
	 *用户的时候,发现freePool中已经没有能用的对象,如果来的用户申请的对象不大于最大值(maxCapacity),
	 *就允许freePool在开一个对象给用户使用。如果lentPool中的对象(用户申请的在使用的对象)已经达到了
	 *最大值,那么该用户就拿不到对象,只能等其它用户释放后才能使用。联想数据库的连接池。recyclerView就是
	 *用的这个原理。
	 */
package com.example.wuyang.lsn4code;

import android.util.SparseArray;
//这里可以存放任何对象,我们用泛型
public abstract class ObjectPool<T> {
    //空闲沲,用户从这个里面拿对象
	//对象池保存的东西不多,所以使用SparseArray,不使用HashMap,为了节省内存。
	//freePool表示能用的对象池
    private SparseArray<T> freePool;
    //lentPool表示正在使用对象池,用户正在使用的对象放在这个沲记录
    private SparseArray<T> lentPool;

    //沲的最大值

    private int maxCapacity;

    public ObjectPool(int initialCapacity, int maxCapacity) {
        //初始化对象沲
        initalize(initialCapacity);
        this.maxCapacity=maxCapacity;
    }

    private void initalize(int initialCapacity) {
        lentPool=new SparseArray<>();
        freePool=new SparseArray<>();
        for(int i=0;i<initialCapacity;i++){
			//对象创建交给子类去实现
            freePool.put(i,create());
        }
    }

    /**
     * 申请对象
     * @return
     */
    public T acquire() throws Exception {

        T t=null;
		//可能有很多线程申请
        synchronized (freePool){
			//得到空闲的对象的数量
            int freeSize=freePool.size();
			//轮训池
            for(int i=0;i<freeSize;i++){
				//找到该对象
                int key=freePool.keyAt(i);
				//得到池中的对象
                t=freePool.get(key);
				//找到的对象不为空
                if(t!=null){
					//我们就把找到的对象放到另外一个(lentPool)池里
                    this.lentPool.put(key,t);
                    this.freePool.remove(key);
                    return t;
                }
            }
            //如果没对象可取了
            if(t==null && lentPool.size()+freeSize<maxCapacity){
                //这里可以自己处理,超过大小
                if(lentPool.size()+freeSize==maxCapacity){
                    throw new Exception();
                }
                t=create();
                lentPool.put(lentPool.size()+freeSize,t);


            }
        }
        return t;
    }

    /**
     * 回收对象
     * @return
     */
    public void release(T t){
        if(t==null){
            return;
        }
		//对象在池里面的索引,就是找该对象的键。
        int key=lentPool.indexOfValue(t);
        //释放前可以把这个对象交给用户处理
        restore(t);

        this.freePool.put(key,t);
        this.lentPool.remove(key);

    }

    protected  void restore(T t){

    };


    protected abstract T create();

    public ObjectPool(int maxCapacity) {
        this(maxCapacity/2,maxCapacity);
    }

}

We create your own objects pool

package com.example.wuyang.lsn4code;

public class MyObjectPool extends ObjectPool{
    public MyObjectPool(int initialCapacity, int maxCapacity) {
        super(initialCapacity, maxCapacity);
    }

    public MyObjectPool(int maxCapacity) {
        super(maxCapacity);
    }

    @Override
    protected Object create() {//LRU
        return new Object();
    }
}

Look how to use MainActivity in.

 MyObjectPool pool=new MyObjectPool(2,4);
        Object o1=pool.acquire();
        Object o2=pool.acquire();
        Object o3=pool.acquire();
        Object o4=pool.acquire();
        Object o5=pool.acquire();

        Log.i("jett",o1.hashCode()+"");
        Log.i("jett",o2.hashCode()+"");
        Log.i("jett",o3.hashCode()+"");
        Log.i("jett",o4.hashCode()+"");
        Log.i("jett",o5.hashCode()+"");

HashCode printout four different values. Fifth
Here Insert Picture Description
second point 9, and associated objects Activity not written static.
Third 9, such as inner classes are defined as follows

private class MyAsyncTask2 extends AsyncTask{
}

Solution, using weak references, then this class is written as a separate file

  private class MyAsyncTask2 extends AsyncTask{

        private WeakReference<Main2Activity> main2Activity;

        public MyAsyncTask2(Main2Activity main2Activity){
            this.main2Activity=new WeakReference<>(main2Activity);
        }

        @Override
        protected Object doInBackground(Object[] objects) {
            return doSomeing();
        }

        private Object doSomeing() {
            //做了很多事后
            return new Object();
        }
    }

The fourth point 9
we write a single-mode embodiment comprises a callback function, as follows

package com.example.administrator.lsn6_demo;

import android.view.View;
import android.widget.Button;

import java.lang.ref.WeakReference;

public class Singleton {
    private static Singleton singleton;
    private Callback callback;
    public static Singleton getInstance(){
        if(singleton==null){
            singleton=new Singleton();
        }
        return singleton;
    }



    public void setCallback(Callback callback){
        this.callback=callback;
    }
    public Callback getCallback(){
        return callback;
    }
    public interface Callback{
        void callback();
    }

}

MainActivity call

//这里使用了匿名内部类,会造成内存泄漏
  Singleton.getInstance().setCallback(new Singleton.Callback() {
            @Override
            public void callback() {
           //这里已经持有Activity的引用
           //单例是永不释放的东西,单例在 apk进程中是不会释放的,当然如果单例所属的进程没有了 
           // 单例也会被释放的

            }
        });

    }

Singleton into the following

package com.example.administrator.lsn6_demo;

import android.view.View;
import android.widget.Button;

import java.lang.ref.WeakReference;

public class Singleton {
    private static Singleton singleton;
//    private Callback callback;
    private WeakReference<Callback> callback;
    public static Singleton getInstance(){
        if(singleton==null){
            singleton=new Singleton();
        }
        return singleton;
    }



    public void setCallback(Callback callback){
        this.callback=new WeakReference<>(callback);
    }
    public Callback getCallback(){
        return callback.get();
    }
    public interface Callback{
        void callback();
    }

}

9 Handler fifth point of the problem, there are two places should be noted that
the first place to note:
see one line of code Handler

 Handler handler=new Handler(Looper.myLooper());
 handler.sendMessage(new Message());

Loop Application life cycle is the same, the entire program does not quit, handler never release, which also led to a corresponding Activity can not be released.
Solutions, weak references a single write a class +


class MyHandler extends Handler{
    private WeakReference m;
    public MyHandler(Main2Activity activity){
        m=new WeakReference(activity);
    }
    }

The second place to note

  m.post(new Runnable() {
           @Override
          public void run() {

           }
       }
       );

This is a non-static inner classes leakage problems. Solution, write a separate class.
In either case, we are in onDestroy () in such a way.

 @Override
    protected void onDestroy() {
        super.onDestroy();
        //清楚所有的回调和消息
        handler.removeCallbacksAndMessages(null);
    }
}

Guess you like

Origin blog.csdn.net/qczg_wxg/article/details/89815974