简述

  在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的情况

最新文章

  1. php 文件日志类
  2. SQL SERVER With语法[转]
  3. 正确的选择log级别
  4. js之函数
  5. 操作系统—Systemd
  6. 关于 Android导出apk时碰到的[Unable to execute dex: Multiple dex files define]
  7. 记拿到鹅厂前端开发暑期实习offer的经历
  8. 【风马一族_xml】xml的基本讲解笔记
  9. Asp.net vNext 2
  10. Django查询的琐碎记录
  11. 输入 URL 到页面完成加载过程中的所有发生的事情?
  12. HTML5获取当前的经纬度坐标
  13. eclipse使用maven tomcat插件部署无法关联源代码
  14. Go语言中的Struct
  15. js-day05-JSON-jQuery初体验
  16. Linux关于文件,文件夹操作命令
  17. Java int类型与String类型互转
  18. 深入理解Plasma(一)Plasma 框架
  19. asp.net mvc 加三层架构 完美搭配
  20. MySQL 数据类型的简单选择

热门文章

  1. MYSQL常用命令2
  2. rem,em,与px的比较用法
  3. ideal的maven工程启动时老是报错,提示web.xml里面的监听器找不到,但是实际又是存在的
  4. systemd的新特性及unit常见类型分析与awk用法示列
  5. Python基础:八、python基本数据类型
  6. Spark源码系列:DataFrame repartition、coalesce 对比
  7. CodeForce edu round 53 Div 2. D:Berland Fair
  8. HNOI2006公路修建问题
  9. JS制作图片切换
  10. Mysql逆向工程效率神器之使用IDE自动生成Java实体类