原文:http://blog.csdn.net/newcman/article/details/7675592
下文转摘至:点击打开链接
Android应用在T-MobileG1上被限制只能使用16MB的内存。这对于手机来说已经是很大的内存了但对于很多开发者来说却仍然有点少。就算你不想把内存耗尽,你也应该尽可能的节约内存来避免其它应用不足以运行。Android保存在内存里的应用越多,用户切换应用的速度也会越快。作为工作的一部分,在开发Android应用的时候我碰到了很多内存泄漏问题,而绝大部分都出自于一个错误:对Context保持了长期的有效引用。
在Android里,context可以有很多用途,但更多的是加载和访问资源。这也就是为什么很多wedget在它们的构造函数里都会接收一个context参数。一般你可能会碰到两种context:Activity和Application,通常开发者都将前者作为需要传入到类或者方法里的context:
@Override
protected void onCreate(Bundle state) {
super.onCreate(state);
TextViewlabel = new TextView(this);
label.setText("Leaks are bad");
setContentView(label);
}
上面的代码意味着,label这个view持有了整个activity以及activity所拥有的所有资源(通常是整个View层次以及所有的资源)的引用。这就是说,如果你泄漏(意思是你保持了对某一个对象的长期引用使得垃圾回收器无法将其回收)了context,你就泄漏了很多内存,而假如你不加以注意,泄漏整个activity是一件很容易的事情。
当屏幕方向改变时,系统默认会销毁当前activity并创建一个新的保持了之前状态的activity。为此,Android会从资源文件里重新加载应用的UI。现在想象一下假如你的应用里有一张很大的bitmap,而你并不想在每次屏幕旋转的时候都重新加载这张图片,最简单的方式是使用一个静态字段保持对它的引用。
private static Drawable sBackground;
@Override
protected void onCreate(Bundle state) {
super.onCreate(state);
TextViewlabel = new TextView(this);
label.setText("Leaks are bad");
if(sBackground == null) {
sBackground = getDrawable(R.drawable.large_bitmap);
}
label.setBackgroundDrawable(sBackground);
setContentView(label);
}
这段代码很快但是却犯了大错误。它泄漏了第一次屏幕旋转之前创建的第一个activity。当一个Drawable被绑定到一个view时,这个view就被设定成这个drawable的callback了。这意味着这个drawabel拥有了对这个TextView的引用,而这个TextView又拥有对activity的引用。取决于你的代码,activity又会拥有很多其它资源的引用。
这个例子只是context泄漏最简单的一种情况,你可以在源代码里看看我们是怎么通过在activity被销毁的时候将存储的drawables的callbacks置空来解决这个问题。有意思的是,你可以通过很多手段创建一个context泄漏链,那样会更糟糕。他们能让你很快的把内存耗尽。
这里有两个简单的方法来避免Context相关的内存泄漏。最有效的一种方法是避免将context带出它本身的作用域。上个例子说明了,对隐式引用了外部类的内部类的静态引用方式也同样非常危险。(译者:sBackground是静态引用,sBackground对label的隐式引用)第二个解决方案是使用Application上下文。这个context会存活到你的应用终止时,并且不会依存于Activity的生命周期。如果你打算保持一个需要context的长期存活的对象,记住使用Application上下文。可以通过调用Context.getApplicationContext()或者Activity.getApplication()来获得此对象。
总结,避免context相关的内存泄漏,记住以下事项:
不要保持一个对context-activity的长期有效引用(对一个activity的引用的生命周期和这个activity一致)
使用context-application而不是context-activity
如果你不想控制对象的生命周期请避免使用非静态内部类,取而代之是使用内部静态类并保持一个对acticity的弱引用(weakreference)。方法是让内部静态类保持一个对acticity的WeakReference,就像ViewRoot和它的内部类W所做的那样。
垃圾回收器并不是内存泄漏的保险。
一下为VIew的
- setBackgroundDrawable 源码
- public void setBackgroundDrawable(Drawable d) {
- boolean requestLayout = false;
- mBackgroundResource = 0;
- /*
- * Regardless of whether we're setting a new background or not, we want
- * to clear the previous drawable.
- */
- if (mBGDrawable != null) {
- mBGDrawable.setCallback(null);
- unscheduleDrawable(mBGDrawable);
- }
- if (d != null) {
- Rect padding = sThreadLocal.get();
- if (padding == null) {
- padding = new Rect();
- sThreadLocal.set(padding);
- }
- if (d.getPadding(padding)) {
- setPadding(padding.left, padding.top, padding.right, padding.bottom);
- }
- // Compare the minimum sizes of the old Drawable and the new. If there isn't an old or
- // if it has a different minimum size, we should layout again
- if (mBGDrawable == null || mBGDrawable.getMinimumHeight() != d.getMinimumHeight() ||
- mBGDrawable.getMinimumWidth() != d.getMinimumWidth()) {
- requestLayout = true;
- }
- // 以下设置了Drawable 对View的引用
- d.setCallback(this);
- if (d.isStateful()) {
- d.setState(getDrawableState());
- }
- d.setVisible(getVisibility() == VISIBLE, false);
- mBGDrawable = d;
- if ((mPrivateFlags & SKIP_DRAW) != 0) {
- mPrivateFlags &= ~SKIP_DRAW;
- mPrivateFlags |= ONLY_DRAWS_BACKGROUND;
- requestLayout = true;
- }
- } else {
- /* Remove the background */
- mBGDrawable = null;
- if ((mPrivateFlags & ONLY_DRAWS_BACKGROUND) != 0) {
- /*
- * This view ONLY drew the background before and we're removing
- * the background, so now it won't draw anything
- * (hence we SKIP_DRAW)
- */
- mPrivateFlags &= ~ONLY_DRAWS_BACKGROUND;
- mPrivateFlags |= SKIP_DRAW;
- }
- /*
- * When the background is set, we try to apply its padding to this
- * View. When the background is removed, we don't touch this View's
- * padding. This is noted in the Javadocs. Hence, we don't need to
- * requestLayout(), the invalidate() below is sufficient.
- */
- // The old background's minimum size could have affected this
- // View's layout, so let's requestLayout
- requestLayout = true;
- }
- computeOpaqueFlags();
- if (requestLayout) {
- requestLayout();
- }
- mBackgroundSizeChanged = true;
- invalidate();
相关推荐
+viewpager+listview(adapterview)recyclerview scrollview webviewblog//blog.csdn.net/w7822938/article/details/47173047/demo-apk,可30452;
标题中的“博客https://blog.csdn.net/weixin_49457347/article/details/1236所需文件”表明这是一个与特定博客文章相关的压缩包,但没有提供足够的信息来直接解释博客的内容。从描述中也无法获取更多细节,它只是...
https://blog.csdn.net/a6661314/article/details/124358796的实验文件
接前两篇文章,[小学生python游戏编程3----拼图游戏-准备](https://blog.csdn.net/fqfq123456/article/details/127173684),[小学生python游戏编程4----拼图游戏今天]...,上次写到可以打乱图片,拼成游戏界面,今天...
Predict if the car purchased at the Auction is a good bad buy The dependent variable IsBadBuy is binary C2 There are 32 Independent variables C3 C34
详情看我的我的文章https://blog.csdn.net/wsxybz/article/details/128486717
文章链接:https://blog.csdn.net/Jeankyw/article/details/131890436?spm=1001.2014.3001.5502
https://blog.csdn.net/huangjhai/article/details/118854733
使用Weka语料库时需要用到的源文件,详情:http://blog.csdn.net/quantum_bit/article/details/44665555
https://blog.csdn.net/ResumeProject/article/details/123292963
简单的学生信息管理系统,实现对用户类型的不同权限管理(增删改查). 文章介绍:https://blog.csdn.net/qq_56886142/article/details/122740969?spm=1001.2014.3001.5501
https://blog.csdn.net/ChaoChao66666/article/details/12578559的图片
电调测试程序 https://blog.csdn.net/weixin-45902229/article/details/121
http://blog.csdn.net/zhangerqing/article/details/8239539 https://my.oschina.net/viakiba/blog/795797
本人博文 https://blog.csdn.net/hrcsdn13/article/details/141260457?spm=1001.2014.3001.5502 使用图片
位域代码 https://blog.csdn.net/qq_37218325/article/details/124859379
用于步骤4的资源。https://blog.csdn.net/feng8403000/article/details/13408
此更新包仅限于升级已有的程序至最新版(如从V1.0版、V1.1版、V1.2版、V2.0版、V2.1版、V2.5版、V3.0版以及V3.2标准版升级到V3.2增强版),如果您之前...程序链接:http://blog.csdn.net/vbcom/article/details/7245186
linux-5.8.6内核源码。链接https://blog.csdn.net/tan1666/article/details/123156383
元旦倒计时代码 参考https://blog.csdn.net/m0_38139250/article/details/1284