避免Android中Context引起的内存泄露

Android |双锁单例模式中使用Context如何避免内存泄露的 Warning 提示 在Android开发中,经常会将工具类以单例模式的方法实现,而工具类中又总不可避免的用到。查阅了大量资料后,解决方法如文中所示。值得注意的是,在我查阅的所有资料中,基本所有解决方法有内存泄漏的风险。包括 Google 自己的。 阅读详情

Context是我们在编写Android程序经常使用到的对象,意思为上下文对象。 常用的有Activity的Context还是有Application的Context。Activity用来展示活动界面,包含了很多的视图,而视图又含有图片,文字等资源。在Android中内存泄露很容易出现,而持有很多对象内存占用的Activity更加容易出现内存泄露,开发者需要特别注意这个问题。

本文讲介绍Android中Context,更具体的说是Activity内存泄露的情况,以及如何避免Activity内存泄露,加速应用性能。

Drawable引起的内存泄露

Drawable引起内存泄露这个问题是比较隐晦,难以察觉的。在阅读了Romain Guy的Avoiding memory leaks,结合grepcode查看源码才明白了。

在Android系统中,当我们进行了屏幕旋转,默认情况下,会销毁掉当前的Activity,并创建一个新的Activity并保持之前的状态。在这个过程中,Android系统会重新加载程序的UI视图和资源。假设我们有一个程序用到了一个很大的Bitmap图像,我们不想每次屏幕旋转时都重新加载这个Bitmap对象,最简单的办法就是将这个Bitmap对象使用static修饰。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private static Drawable sBackground;

@Override
protected void onCreate(Bundle state) {
  super.onCreate(state);

  TextView label = new TextView(this);
  label.setText("Leaks are bad");

  if (sBackground == null) {
    sBackground = getDrawable(R.drawable.large_bitmap);
  }
  label.setBackgroundDrawable(sBackground);

  setContentView(label);
}

但是上面的方法在屏幕旋转时有可能引起内存泄露,无论是咋一看还是仔细看这段代码,都很难发现哪里引起了内存泄露。

当一个Drawable绑定到了View上,实际上这个View对象就会成为这个Drawable的一个callback成员变量,上面的例子中静态的sBackground持有TextView对象lable的引用,而lable只有Activity的引用,而Activity会持有其他更多对象的引用。sBackground生命周期要长于Activity。当屏幕旋转时,Activity无法被销毁,这样就产生了内存泄露问题。

2.3.7及以下版本Drawable的setCallback方法的实现

1
2
3
public final void setCallback(Callback cb) {
    mCallback = cb;
}

好在从4.0.1开始,引入了弱引用处理这个问题,弱引用在GC回收时,不会阻止GC回收其指向的对象,避免了内存泄露问题。

1
2
3
public final void setCallback(Callback cb) {
    mCallback = new WeakReference<Callback>(cb);
}

单例引起的内存泄露

单例是我们比较简单常用的一种设计模式,然而如果单例使用不当也会导致内存泄露。 比如这样一个例子,我们使用饿汉式初始化单例,AppSettings我们需要持有一个Context作为成员变量,如果我们按照下面的实现其实是有问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
public class AppSettings {    
    private Context mAppContext;
    private static AppSettings sInstance = new AppSettings();

    //some other codes
    public static AppSettings getInstance() {
      return sInstance;
    }
  
    public final void setup(Context context) {
        mAppContext = context;
    }
}

sInstance作为静态对象,其生命周期要长于普通的对象,其中也包含Activity,当我们进行屏幕旋转,默认情况下,系统会销毁当前Activity,然后当前的Activity被一个单例持有,导致垃圾回收器无法进行回收,进而产生了内存泄露。

解决的方法就是不持有Activity的引用,而是持有Application的Context引用。代码如下修改

1
2
3
public final void setup(Context context) {
    mAppContext = context.getApplicationContext(); 
}

访问这里了解更多关于单例模式的问题

条条方法返回Context

通常我们想要获取Context对象,主要有以下四种方法

  • View.getContext,返回当前View对象的Context对象,通常是当前正在展示的Activity对象。
  • Activity.getApplicationContext,获取当前Activity所在的(应用)进程的Context对象,通常我们使用Context对象时,要优先考虑这个全局的进程Context。
  • ContextWrapper.getBaseContext():用来获取一个ContextWrapper进行装饰之前的Context,可以使用这个方法,这个方法在实际开发中使用并不多,也不建议使用。
  • Activity.this 返回当前的Activity实例,如果是UI控件需要使用Activity作为Context对象,但是默认的Toast实际上使用ApplicationContext也可以。

其他内存泄露问题

避免内存泄露须谨记

  • 不要让生命周期长于Activity的对象持有到Activity的引用
  • 尽量使用Application的Context而不是Activity的Context
  • 尽量不要在Activity中使用非静态内部类,因为非静态内部类会隐式持有外部类实例的引用(具体可以查看细话Java:”失效”的private修饰符了解)。如果使用静态内部类,将外部实例引用作为弱引用持有。
  • 垃圾回收不能解决内存泄露,了解Android中垃圾回收机制
原文:http://blog.youkuaiyun.com/boyupeng/article/details/46503221
Android的context使用 家好,今天给大家分享一下Android里的Context的一些用法,以前经常有人在群里问我比如我在一个工具类里的某个方法,或者View里需要调用Context.但是工具类还有View里没有这个上下文怎么办?为了解决大家的疑问,我今天写一个简单的Demo.让大家如何学好自如的用Context.想什么时候有Context,什么时候就有Context 立即下载

相关推荐

同花顺CM函数深度解析:如何精准设置历史换手衰减系数以优化筹码峰

本文深度解析同花顺CM函数中的历史换手衰减系数,揭示其如何影响筹码峰准确性。通过拆解CM函数参数,并提供基于前十大流通股东锁定比例的计算公式,指导用户精准设置该系数,从而优化筹码峰模型,使其更真实反映个股持仓成本分布,提升技术分析的有效性。

mango的博客 1773

Android的Context泄露分析和解决方案

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34249367的博客 534

Lumerical INTERCONNECT 中的自相位调制 (SPM) 仿真实践指南

本文详细介绍了在Lumerical INTERCONNECT中进行自相位调制(SPM)仿真的实践指南。从SPM的基础物理原理出发,深入解析非线性薛定谔方程和克尔效应,到INTERCONNECT中NLSE波导元件的配置技巧,以及时域与频域中SPM效应的观测方法。文章还提供了常见问题排查和进阶联合仿真技巧,帮助用户高效完成从仿真到实测的校准过程。

weixin_42565652的博客 187

Android内存泄露案例和解析

使用过长对象生命周期 静态变量 单例 使用内部类 耗时操作 Handler.delay http://www.cnblogs.com/qianxudetianxia/p/3645106.html https://drakeet.me/android-leaks http://www.tuicool.com/articles/2AnARj http://www.

我早就想,要这样载着你,翻山越岭 2463

程序进入hardfault之后查找原因的方法

如果在MCU运行程序的时候,进入了hardfault,该怎么办?

smart_boy__的博客 761

瑞芯微rv1126 rtsp+mpp+rga取流

瑞芯微rv1109 rtsp+mpp+rga取流

ZuoSeDiao的博客 6338

android 避免内存泄露

原文链接不详:如有人知道原文链接,请告诉我。我重新编辑加上链接 Android应用程序被限制在16MB的堆上运行,至少在T-Mobile G1上是这样。对于手机来说,这是很大的内存了;但对于一些开发人员来说,这算是较小的了。即使你不打算使用掉所有的内存,但是,你也应该尽可能少地使用内存,来确保其它应用程序得以运行。Android在内存中保留更多的应用程序,对于用户来说,程序间切换就能...

倚风听雪 206

VOWIFI--相关的协议文档

一、3GPP相关协议文档 3GPP 23.402 Architecture enhancements for non-3GPP accesse- //重要 整体框架结构和流程,3GPP和NON-3GPP切换 3GPP 36.304  User Equipment (UE) procedures in idle mode //重要,终端在空闲状态下3GPP与NON-3GPP之间的重选方法   3GP

时九博客 3578

【干货】避免Android中Context引起的内存泄露

视频汇总首页:http://edu.51cto.com/lecturer/index/user_id-4626073.htmlContext是我们在编写Android程序经常使用到的对象,意思为上下文对象。 常用的有Activity的Context还是有Application的Context。Activity用来展示活动界面,包含了很多的视图,而视图又含有图片,文字等资源。在Android中内存泄...

weixin_34326429的博客 99

Linux密码破解(使用hydra工具和使用john暴力破解)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录一、使用hydra离线破解linux密码1.准备实验环境2.创建用户名字典3.hydra密码爆破二、复制shadow文件,使用john暴力破解1.实验环境1.复制linux的shadow文件2.john暴力破解 一、使用hydra离线破解linux密码 1.准备实验环境 ①攻击机:kali_linux 2021.2(ifconfig查询IP地址:192.168.119.132) ②靶机:Ubantu 16.04(ifconfig

weixin_46447549的博客 2万+

学Simulink——基于Simulink的PMSM矢量控制(FOC)从零搭建

《Simulink下PMSM矢量控制(FOC)全流程开发指南》 本教程系统讲解了基于Simulink的永磁同步电机(PMSM)磁场定向控制(FOC)实现方法。主要内容包括:FOC控制原理与双闭环架构设计、Simulink建模全流程(含PMSM本体建模、坐标变换、PI控制器设计等)、关键调试技巧以及工程扩展方向。教程以48V伺服电机为例,详细演示了从Clarke/Park变换到SVPWM生成的完整实现过程,并提供了参数配置建议和常见问题解决方案。通过本教程,读者可掌握FOC系统的核心实现技术,为开发高性能电机

xiaoheshang_123的博客 273

Android中避免Context引起内存泄露

1.Context:上下文对象                  xxActivity.this getApplicationContext 2.Activity用来展示活动界面,包含了很多的视图,而视图又含有图片,文字等资源。在Android中内存泄露很容易出现,而持有很多对象内存占用的Activity更加容易出现内存泄露,开发者需要特别注意这个问题。 目标:一.Activity内存泄露

weishiwei0923的专栏 372

三态门Multisim电路仿真——硬件工程师笔记

三态门原理及应用摘要 三态门是具有高电平(1)、低电平(0)和高阻态(Z)三种输出的逻辑电路,通过使能端(EN)控制状态切换。高阻态时输出端等效断路,避免信号冲突。其核心应用包括: 总线系统:多设备共享总线时,仅使能选中设备的三态门,其余保持高阻态,防止干扰。 数据选择器:利用三态门切换多路输入信号,简化电路设计。 实现方式分两种: TTL三态门(三极管构成):低电平使能有效,仿真验证输出逻辑与高阻态。 MOS三态门(MOS管构成):高电平使能有效,仿真显示使能信号控制输出状态。 文中还附硬件工程师笔试面试

XU157303764的博客 2004

android开发避免Context引起的内存泄露问题

原文地址http://blog.youkuaiyun.com/adreamer_bj/article/details/52099278android开发中不可避免要引用到Context对象,但是Context又极易引起内存泄露,所以必须明白Context的引用用法才能写好程序注意编码时保持几个原则:不要让生命周期长于Activity的对象持有到Activity的引用 尽量使用Application的Conte

果酱大师的博客 1109

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

避免 Android 中 Context 引起的内存泄露

Context 在编写Android程序时经常使用,意思为上下文对象。 常用的有Activity的Context还是有Application的Context。Activity用来展示活动界面,包含了很多的视图,而视图又含有图片,文字等资源。在Android中内存泄露很容易出现,而持有很多对象内存占用的Activity更加容易出现内存泄露,开发者需要特别注意这个问题。 本文讲介绍Andr

djwmzyl的专栏 345

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

避免Android中context引起的内存泄露

Context是我们在编写Android程序经常使用到的对象,意思为上下文对象。 常用的有Activity的Context还是有Application的Context。Activity用来展示活动界面,包含了很多的视图,而视图又含有图片,文字等资源。在Android中内存泄露很容易出现,而持有很多对象内存占用的Activity更加容易出现内存泄露,开发者需要特别注意这个问题。 本文讲介绍An...

Java和Android架构 209

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Android 如何避免 Context 内存泄露

Activity Context 的内存泄露 Android 中的 Activity Context 内存泄露,简单说就是 Activity 调用 onDestroy() 方法销毁后,此 Activity 还被其他对象强引用,导致此 Activity 不能被 GC(JAVA 垃圾回收器) 回收,最后出现内存泄露。 原因主要有两个: 静态的 Activity Context 或 任何包含 Acti...

weixin_34241036的博客 419
上一篇: Android中Handler引起的内存泄露
下一篇: Java强引用、软引用、弱引用、虚引用详解
djyjava
博客等级 码龄19年 3粉丝 10原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值