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


簡述

  在Android開發的過程中,難免會使用單例模式或者靜態方法工具類.我們會讓它們持有一些外部的Context或者View一般有以下幾種情況:

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

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

 

Context的類型認識

  在講解關於靜態持有Context之前,我們需要來認識一下Context自己的區別,原則上Context其實只有2種(盡管Activity/Fragment/Service/都有Context,但是實際上他們屬於一個類型的Context)

  第一種

應用的Context,下面的2行代碼都是調用應用的Context,這個Context在一個app里只會有一個.並且在App啟動時創建,App關閉時消亡,所以這個Context是貫徹App生命周期全程的.

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

  第二種

Activity 或者 Service 自己,Activity 或 Service自己本身就是Context,這種Context的生命周期只在Activity或Service的生命周期下,關閉了Activity后Context理所應當的也隨着消亡.有多少Activity和Service就會有多少個Context,並且重復多次創建某個Activity的時候Context也是多個

 

單例模式持有Context的情況

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

首先說明,持有View和持有Context都是一樣的道理,所以我這里就不在驗證持有View的情況

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

 首先我們創建一個簡單的單例模式,並且讓它的全局變量持有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的情況

 

待續...

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM