简述

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

Android开发 静态static类与static方法持有Context是否导致内存泄露的疑问的更多相关文章

  1. 【Android开发坑系列】之经常被忽略的背景图片内存泄露

    我们平时设置图片的时候,几乎都忘记回收老的(背景)图片,比如: TextView.setBackgroundDrawable() TextView.setBackgroundResource() Im ...

  2. Java | 静态嵌套类(Static Nested Class)

    前言 本文内容主要来自 Java 官方教程中的<嵌套类>章节. 本文提供的是 JDK 14 的示例代码. 定义 静态嵌套类(Static Nested Class),是 Java 中对类的 ...

  3. Android开发之清除缓存功能实现方法,可以集成在自己的app中,增加一个新功能。

    作者:程序员小冰,CSDN博客:http://blog.csdn.net/qq_21376985 Android开发之清除缓存功能实现方法,可以集成在自己的app中,增加一个新功能. 下面是一个效果图 ...

  4. Android开发——RecyclerView特性以及基本使用方法(一)

    )关于点击事件,没有像ListView那样现成的API,但是自己封装起来也不难,而且我们使用ListView时,如果item中有可点击组件,那么点击事件的冲突也是一个问题,而在RecyclerView ...

  5. Android开发——RecyclerView特性以及基本使用方法(二)

    0.  前言 随着Android的发展,虽然ListView依旧重要,但RecyclerView确实越来越多的被大家使用.但显然并不能说RecyclerView就一定优于ListView,而是应该根据 ...

  6. android: Context引起的内存泄露问题

    错误的使用Context可能会导致内存泄漏,典型的例子就是单例模式时引用不合适的Context. public class SingleInstance { private static Single ...

  7. 【转】Android开发中让你省时省力的方法、类、接口

    转载 http://www.toutiao.com/i6362292864885457410/?tt_from=mobile_qq&utm_campaign=client_share& ...

  8. 29个android开发常用的类、方法及接口

    在安卓开发中,我们常常都需要借助各种各样的方法.类和接口来实现相关功能.提升开发效率,但对于初学者而言,什么时候该用什么类.方法和接口呢?下面小编整理了29个,日常开发中比较常用的类.方法.接口及其应 ...

  9. Android开发中Parcelable接口的使用方法

    在网上看到很多Android初入门的童鞋都在问Parcelable接口的使用方法,小编参考了相关Android教程,看到里面介绍的序列化方法主要有两种分别是实现Serializable接口和实现Par ...

随机推荐

  1. Linux下tomcat运行时jvm内存分配

    tomcat运行时jvm内存分配 ⑴开发环境下在myeclipse中配置-Xms256m -Xmx512m -XX:NewSize=64m -XX:MaxNewSize=128m -XX:PermSi ...

  2. XSS学习(三)挖掘思路

    HTML标签之间 <div id="body"> [输出点] </div> payload:<script>alert(1)</scrip ...

  3. MFC中给各个控件填充背景颜色的方法

    1.给程序设置大背景色,在OnPaint()函数中添加如下代码: CRect rect; CPaintDC dc(this); GetClientRect(rect); dc.FillSolidRec ...

  4. 反向Ajax:WebSocket

    郭晨 软件151 1531610114 WebSocket 在HTML5中出现的WebSocket是一种比Comet还要新的反向Ajax技术,WebSocket启用了双向的全双工通信信道,许多浏览器( ...

  5. LG3211 [HNOI2011]XOR和路径

    题意 题目描述 给定一个无向连通图,其节点编号为 1 到 N,其边的权值为非负整数.试求出一条从 1 号节点到 N 号节点的路径,使得该路径上经过的边的权值的"XOR 和"最大.该 ...

  6. BZOJ5311,CF321E 贞鱼

    题意 Problem 5311. -- 贞鱼 5311: 贞鱼 Time Limit: 3 Sec  Memory Limit: 162 MBSubmit: 677  Solved: 150[Subm ...

  7. java基础(二):java内部类

    内部类像寄生虫一样生存在其他类[外部类]的内部.定义在类的内部的类叫内部类,它缩小了可见性.根据内部类定义结构的不同,可以把内部类分为 成员内部类和局部内部类.成员内部类定义的地方和外部类的成员变量和 ...

  8. JNI学习笔记_Java调用C —— 非Android中使用的方法

    一.学习笔记 1.java源码中的JNI函数本机方法声明必须使用native修饰. 2.相对反编译 Java 的 class 字节码文件来说,反汇编.so动态库来分析程序的逻辑要复杂得多,为了应用的安 ...

  9. Java高级特性 第10节 IDEA和Eclipse整合JUnit测试框架

    一.IDEA整合Junit测试框架 1.安装插件 打开File菜单的下拉菜单settings[设置] : 点击左侧Plugins[插件]菜单 在输入框中输入JUnitGenerator 2.0,点击I ...

  10. 2018-2019-2 网络对抗技术 20165308 Exp3 免杀原理与实践

    2018-2019-2 网络对抗技术 20165308 Exp3 免杀原理与实践 实践内容(3.5分) 1.1 正确使用msf编码器(0.5分),msfvenom生成如jar之类的其他文件(0.5分) ...