Android開發 靜態static類與static方法持有Context是否致使內存泄露的疑問

簡述

  在Android開發的過程當中,不免會使用單例模式或者靜態方法工具類.咱們會讓它們持有一些外部的Context或者View通常有如下幾種狀況:app

  1.   單例模式,類的全局變量持有Context 或 View (注意!持有View和持有Context實際上是同樣的) ----->此方式會內存泄露
  2.   單例模式,方法引入Context  ----->此方式不會內存泄露
  3.   工具類靜態方法持有Context 或 View
  4.   工具類靜態變量持有Context 或 View

  上面我已經說明了會內存泄露的狀況,咱們就來逐一詳細說明下如何操做,和證實他們是否會內存泄露ide

 

Context的類型認識

  在講解關於靜態持有Context以前,咱們須要來認識一下Context本身的區別,原則上Context其實只有2種(儘管Activity/Fragment/Service/都有Context,可是實際上他們屬於一個類型的Context)工具

  第一種

應用的Context,下面的2行代碼都是調用應用的Context,這個Context在一個app裏只會有一個.而且在App啓動時建立,App關閉時消亡,因此這個Context是貫徹App生命週期全程的.this

Context applicationContext = getApplicationContext();
Context baseContext = getBaseContext();

  第二種

Activity 或者 Service 本身,Activity 或 Service本身自己就是Context,這種Context的生命週期只在Activity或Service的生命週期下,關閉了Activity後Context理所應當的也隨着消亡.有多少Activity和Service就會有多少個Context,而且重複屢次建立某個Activity的時候Context也是多個spa

 

單例模式持有Context的狀況

第一種狀況 單例模式,類的變量持有Context 或 View  此方式會內存泄露

首先說明,持有View和持有Context都是同樣的道理,因此我這裏就不在驗證持有View的狀況code

 驗證順序是這樣的,我在MainActivity裏反覆啓動退出TestActivity,而後在TestActivity的onCreate方法裏調用單例類而且讓它持有Context,而後咱們在用Android studio自帶的內存泄露工具來分析.在這篇中,我將貼全代碼,後續只會將單例類或者工具類貼出.blog

 首先咱們建立一個簡單的單例模式,而且讓它的全局變量持有Context生命週期

public class SingleMode {
    private static SingleMode mSingleMode;
    private Context mContext;
    private SingleMode(){

    }

    public static synchronized SingleMode I(){
        if (mSingleMode == null){
            mSingleMode = new SingleMode();
        }

        return mSingleMode;
    }

    public void setContext(Context context){
        this.mContext = context;
    }
}

而後讓TestActivity裏讓調用這個單例類內存

public class TestActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test);
        SingleMode.I().setContext(this);

    }
}

而後咱們在MainActivity裏啓動這個TestActivity開發

public class MainActivity extends AppCompatActivity {
    private static final String TAG = MainActivity.class.getName();
    private Button btn1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btn1 = findViewById(R.id.btn1);
        btn1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this,TestActivity.class);
                startActivity(intent);
                
            }
        });    
    }
}

手動反覆進出屢次,而後咱們在退出到MainActivity裏,抓取內存泄露信息

從內存泄露分析裏,能夠看到我已經返回到MainActivity有一段時間了,而且主動手動清理一次內存,可是在查找包下面咱們依然能夠看到TestActivity在存活,而且存活了多個,而SingleMode在存活是正常的由於靜態存活時間是最長的.換句話說就是由於SingleMode在存活而且持有Context才致使內存泄露了

第二種狀況 單例模式,方法引入Context

工具類持有Context的狀況

相關文章
相關標籤/搜索