全局context微信视频会不会泄漏导致内存泄漏

你真的会用Context么?_AndroidDeveloper_传送门
你真的会用Context么?
AndroidDeveloper
本篇文章是受我影响很大的一位粉丝「MeloDev」的投稿,其实每天都有大量的粉丝找我投稿,但是本着对大家的负责,我都会认真审核,不求文章内容多么高级,但是一定是用心写,并且我自己觉得还不错的文章才会通过,因为不想把投稿的文章放在二级文章列表之后,本着每天尽量只发一篇精品文章,导致很多不错的投稿文章发布比较慢,这篇文章其实都是上周五就找我了,还请见谅!另外这个公号全部都是我个人在维护,但是我自己本身在薄荷的工作非常之忙,能坚持下来着实不容易,现在几乎牺牲了我所有业余时间,包括我每天的午睡时间、晚上下班之后的时间以及周末的时间,我已经记不清有多久没有打过一把Dota了。写作这种分享方式是我本身比较喜欢的,这个号我很认真的在维护,大部分都是我原创文章,投稿的文章我也会亲自审核,每个赞赏的人我都会亲自回复表达谢意,有时候如果刚好在看某些电子书或者文章之类的,觉得不错顺便就回复给赞赏支持我的人了,所有的留言我都会一一过目,我每天产生的原创文章大多都是参考留言里大家最迫切的需求,我自认为个人公号很少有我这么认真的了!有一些在线教育邀请了我无数次去他们平台给付费用户做直播或者录课程,我一看那些付费用户的价格,真的吓到了,平均一节课45分钟要两三百块,我跟他们说为什么价格就不能放开让所有人接受呢?比如10块、20块一节课,这多么亲民,大家也能接受。我一直认为好的知识需要付费,但是这价格未免太过昂贵了!一是没时间,二是我着实不喜欢这功利性质的分享,虽然可能我会赚的比现在多得多,但是我还是选择继续以我喜欢的方式给大家做分享。只希望大家对我多多支持,依据个人经济能力赞赏,金额随意,哪怕是一块钱,对你可能没什么,但是却是对我莫大的鼓励。留言区上方的广告也请大家坚持点击下,你们并不会损失什么,但是我却可以靠这点小钱每天多给我媳妇买点水果吃,媳妇靠我的努力每天都能有免费的水果吃想想都好开心...写在前面Context对象在我们的项目中实在是太常见了,启动Activity、Service、发送一个Broadcast,作为获取各种系统Resources的参数,Layout Inflation的参数,show a Dialog的参数等等。Context对象的使用不当,是可能造成内存泄漏的,当你的工程代码已经达到十几万行甚至是几十万行时,Context对象就对内存泄漏造成非常可观的影响了,所以我们应该对Context对象的使用,做到心中有数。什么是Context前两天刚刚对 Context 写了一篇比较长的博客,借鉴大牛们的经验,对 Context 进行了比较详细的整合与总结,花半个小时的时间耐心读一读吧!「你足够了解 Context 吗?」一句话总结:Context是为一个Android程序提供各种功能、资源、服务的一个环境, Context 的资源在系统中只有一套,因为它的子类(Application、Activity、Service)对这同一块资源处理方式的不同,让Context 对象在功能上表现出各自之间的差异。Context对象之间的差异相信如果你是一个初学者, Context 在你手里应该是胡乱传入的,哪里有 Context 就找哪里,各种this乱入,O(∩_∩)O哈哈,至少当时我是这样的,但是 Context 不同的对象在使用功能上是有区别的,比如以下代码:在清单文件中做以下配置:在界面中show a Dialog点击按钮之后崩溃信息当我使用Application的Context时,是无法弹出一个Dialog的,因为Dialog作为一个View,依附在Activity上,并且与Theme相关,当传入参数为Actvity的Context时,崩溃就解决了。下面这张表展示出了Context对象之间使用上的差异:Context相关的内存泄漏问题在讨论内存泄漏之前,先简单的说说Android中内存的回收Dalivik虚拟机扮演了常规的垃圾回收角色,为了GC能够从App中及时回收内存,我们需要时时刻刻在适当的时机来释放引用对象,Dalvik的GC会自动把离开活动线程的对象进行回收。什么是Android内存泄漏:虽然Android是一个自动管理内存的开发环境,但是垃圾回收器只会移除那些已经失去引用的、不可达的对象,在十几万、几十万行代码中,由于你的失误使得一个本应该被销毁的对象仍然被错误的持有,那么该对象就永远不会被释放掉,这些已经没有任何价值的对象,仍然占据聚集在你的堆内存中,GC就会被频繁触发,多说几句,如果手机不错,一次GC的时间70毫秒,不会对应用的性能产生什么影响,但是如果一个手机的性能不是那么出色,一次GC时间120毫秒,出现大量的GC操作,我相信用户就能感觉到了吧。这些无用的引用堆积在堆内存中,越积越多最终导致Crash,有关一些性能优化推荐给大家一个我总结的博客。「Android性能优化总结」有些跑题了,我们赶紧来看看什么情况下Context会引发内存泄漏错误的单例模式我们来分析一下这个非线程安全的单例模式,假设你在Activity A去getInstance获得instance对象,顺手传了一个this,好了,现在一个常驻内存的Singleton保存了你传入Activity A的对象,并且一直持有Activity A的引用,这样即使你Activity被销毁掉,但是因为它的引用还存在于一个Singleton中,是不可能被GC掉的,这样就导致了内存泄漏。View持有Activity的引用再来分析一下,有一个静态的Drawable对象,当我给ImageView设置这个Drawable时,ImageView像上面那个例子一样,保存了这个mDrawable的引用(大家可以点开源码705行去看,很多UI组件都是统一的操作,一直持有传入的对象),然而ImageView传入了this,也就是ImageView同样持有一个MainActivity的mContext。因为被static修饰的mDrawable是常驻内存的,MainActivity是它的间接引用,所以当MainActivity被销毁时,也不能被GC掉,所以也造成了内存泄漏。使用Context的正确姿势通俗一点说,Context造成的内存泄漏,几乎都是当Context销毁的时候,却还被各种不合理、无端地引用着。那么哪个Context对象是不会被销毁的呢?对了,Application的Context对象可以理解为随着进程存在的,所以当Application的Context能搞定的情况下,并且生命周期长的对象,优先使用Application的Context调用一行代码:LaucherApplication.getContext();回头看看上面那张表格,显然Application的Context不是万能的,涉及UI加载操作时,似乎我们只能使用Activity的Context,所以你当你使用Activity的Context时,你要对持有Activity的对象心中有数,保证它能随着生命周期的销毁而被回收,慎用static关键字,不要因为方便访问就各种static乱入。多说一点,上表中Layout Inflation中只能使用Activity的Context,而各种View在创建时,需要传入的Context参数也是Activity的,大家懂了吧,当解析XML文件的时候,传入的参数也就统一了,相信大家一定能想明白这点。写在最后:给大家推荐一个内存检测的自动化工具,LeakCanary,但是当你曾经写出的代码不规范不负责,已经达到十几万行,几十万行的时候,再去抽丝剥茧试图解开已经打上层层死结的引用关联,是非常难的。所以平时还是要注意下细节哈~微信不支持外链,可以点击「阅读原文」跳转到原博客。对了,微信最新版公众号可以「置顶」了哦,觉得我的公号很赞,不妨设置「置顶」。
觉得不错,分享给更多人看到
AndroidDeveloper 微信二维码
分享这篇文章
4月22日 22:22
AndroidDeveloper 最新文章
AndroidDeveloper 热门文章本帖子已过去太久远了,不再提供回复功能。避免 Android中Context引起的内存泄露
作者:技术小黑屋
字体:[ ] 类型:转载 时间:
本文主要介绍Android中Context引起的内存泄露的问题,这里对Context的知识做了详细讲解,说明如何避免内存泄漏的问题,有兴趣的小伙伴可以参考下
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修饰。
private static Drawable sB
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方法的实现
public final void setCallback(Callback cb) {
mCallback =
好在从4.0.1开始,引入了弱引用处理这个问题,弱引用在GC回收时,不会阻止GC回收其指向的对象,避免了内存泄露问题。
public final void setCallback(Callback cb) {
mCallback = new WeakReference&Callback&(cb);
单例引起的内存泄露
单例是我们比较简单常用的一种设计模式,然而如果单例使用不当也会导致内存泄露。 比如这样一个例子,我们使用饿汉式初始化单例,AppSettings我们需要持有一个Context作为成员变量,如果我们按照下面的实现其实是有问题。
public class AppSettings {
private Context mAppC
private static AppSettings sInstance = new AppSettings();
//some other codes
public static AppSettings getInstance() {
public final void setup(Context context) {
mAppContext =
sInstance作为静态对象,其生命周期要长于普通的对象,其中也包含Activity,当我们进行屏幕旋转,默认情况下,系统会销毁当前Activity,然后当前的Activity被一个单例持有,导致垃圾回收器无法进行回收,进而产生了内存泄露。
解决的方法就是不持有Activity的引用,而是持有Application的Context引用。代码如下修改
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中垃圾回收机制
Avoiding memory leaks
Difference between getContext() , getApplicationContext() , getBaseContext() and “this”
Android – what's the difference between the various methods to get a Context?
以上就是对Android Context 内存泄漏的资料整理,后续继续添加相关资料,谢谢大家的支持!
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具

我要回帖

更多关于 全局变量 内存泄漏 的文章

 

随机推荐