内存泄漏的检测、解决、防止

引言

今天又是没什么事情,好,不多说,直接进入我们的主题吧。

今天说的是关于内存泄漏的检测与解决。这个问题想必对于初学者是个迷,也不知道从何出入手,那么今天这个文章可以帮助你。如果有什么地方写的不好,请谅解,毕竟我还是个孩子!!!

找出内存泄漏与解决

请各位同学打开我们的开发工具(AS),来跟我一起写个内存泄漏的项目(嘻嘻)。不多说,上代码!!!

/**
 * Author    lingchen
 * Email     838878458@qq.com
 * Time      2016/11/3
 * Function  测试内存泄漏
 */
public class MainActivity extends AppCompatActivity {
    private static final String TAG = "Activity";




    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


    }


    /**
     * 跳转到测试内存泄漏的activity
     */
    public void onGoTestLeaked(View view) {
        startActivity(new Intent(this, TestLeakedActivity.class));
    }




    @Override
    protected void onDestroy() {
        Log.e(TAG, "MainActivity -- > onDestroy() called");
        super.onDestroy();
    }
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent">


    <Button
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:onClick="onGoTestLeaked"
        android:text="点我,我就泄漏给你看" />


</RelativeLayout>

别告诉我你看不懂,下面就是我们今天关注的类了,上代码。

/**
 * Author    lingchen
 * Email     838878458@qq.com
 * Time      2016/11/3
 * Function  测试类
 */

public class TestLeakedActivity extends AppCompatActivity {
    private static final String TAG = "Activity";
    public static TestLeaked testLeaked;


    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_testleaked);
        testLeaked = new TestLeaked();
    }


    /**
     * 内存泄漏类
     */
    public class TestLeaked {
    }


    @Override
    protected void onDestroy() {
        Log.e(TAG, "TestLeakedActivity -- > onDestroy() called");
        super.onDestroy();
    }
}

好了,相比大家一看到public static TestLeaked testLeaked;就会知道,这个变量的生命周期就是隶属于appliction了(别问我为啥哈)。那好testLeaked = new TestLeaked();这段代码直接new 一个内部类(会引用Activity)指向静态变量。这样如果我多次进入这个界面,会出现什么效果呢?来跟我一起做,拿起鼠标,打开最下方的Android Monitor,然后选中。

不知道这个界面大家有没有经常用到呢?我也不用多解释这个界面了(哎呀,我的mx4手机啊,要不要打马赛克呢?这肯定是测试机,嗯,是测试机),就不做多解释了,毕竟很简单,界面很清晰。。我们开始运行吧,直接重复MainActivity->TestLeakedActivity->MainActivity…….

这明明是测试喜欢做的事情(2个界面疯狂跳转),好了这就是我的内存图,我们看这个就可以看出内存有泄漏了(本来就知道,还要你说)就在这个时候我们点击一下。

那么AS就会把当前的内存信息生成一个文件展示出来

这里肯定很多人看不明白这是什么鬼,哈哈,不用太明白,来跟我一起点几个按钮,你就知道了

现在看起来是不是舒服多了 ,再来点几个按钮。

这张图大家就可以看到了我们的TestLeakedActivity在内存中存在了8个实力,那么他是被引用的呢?那好我们点击。

点击运行。

我们双击他,就会发现 Reference Tree 窗口显示内容了。

好了 ,想必大家在这里也看到了我们的TestLeakedActivity 被TestLeakedActivityTestLeaked引用(表示内部类)。哈哈,是不是很神奇。

但是呢?不对啊,按理说,我们是多次new TestLeaked()复制给静态变量的,那么以前被他引用的对象就应该释放了啊,内存中应该不会存在这么多的TestLeakedActivity实力啊,按理说只有一个TestLeakedActivity才对呀,难道是回收不及时导致的么?,那好我们手动调用下GC。

然后在截取下内存信息。

哈哈,果然就是没有即使被回收,那么我们说的是对的。上面图片说明了一切。好了既然都找到了内存泄漏的原因,那就去把代码改下喽,

这是第一种办法,第二种办法如下:

好了,更改之后,我们使用第二种方法运行下(理想应该是,TestLeakedActivity不应该存在,内部类TestLeaked存在),好了 运行下,顺便点下GC。

再点开内部类。

好了,完美。

防止内存泄漏,养成良好编码习惯

这个话题网上有太多的文章了,我这边就是写下我自己认为要特别注意的地方:

  1. 谨慎使用static变量,即使使用了,要即时施放强引用的地址,尤其是List,即时清理。
  2. 单例类的context应该使用Appliction。
  3. 好好管理handler,在退出的时候,应该调用handler.removeCallbacksAndMessages(null)。
  4. 管理好线程,例如网络请求,应该在退出的时候,取消网络请求。动画也是,及时的停止动画回收资源。
  5. 结合WeakReference(弱引用),SoftReferecne(软引用)使用。
  6. 尽量限制service生命周期,如果完成任务后就关闭service,那么使用IntentService。

......想不到了。

总结就一句话:注重生命周期。

原文发布于微信公众号 - CSDN技术头条(CSDN_Tech)

原文发表时间:2016-11-07

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Android机动车

Retrofit实现带进度下载

Retrofit是目前最主流的网络框架了,它对网络请求几近完美的封装,大大降低了我们开发者的研发难度,缩短了研发周期。最近项目中遇到了下载视频和图片文件的需求(...

14220
来自专栏QQ音乐技术团队的专栏

记一次全民K歌的crash定位过程

全民K歌4.6版本发布后,出现了一个与RecyclerView相关的Bug,作此记录。

43330
来自专栏酷玩时刻

统一管理项目中的接口回调

无论是 Java Web 开发还是 Android 开发我们都避免不了异步处理业务的逻辑。有异步的出现一定就有异步结果(接口)的回调。你之前是不是有为每一个异步...

10240
来自专栏Android先生

Android App优化之提升你的App启动速度之实例挑战

以之前写的Github App:https://github.com/mingjunli/GithubApp为例.

13030
来自专栏Android相关

AAC---LiveData

LiveData是一个与Activity/Fragment生命周期相关(lifecycle-aware)的Observer类。而这种相关性(awareness ...

12820
来自专栏Android小菜鸡

Context的一点理解

  Content即上下文对象,在我们android开发中随处可见,并不陌生。在加载资源、启动一个新的Activity、获取系统服务、获取内部文件(夹)路径、创...

9440
来自专栏刘望舒

lifecycle-mvp,像前端那样组合式写页面

32740
来自专栏24K纯开源

Android开发中遇到的requestFeature() must be called before adding content异常

缘起     上一篇博文中讲到了几种实现全屏显示Activity内容的方法。然而实际在实现中发现了一些问题,在本篇博文中进行总结下。首先交代一下开发环境,本人使...

42270
来自专栏向治洪

Android Remote Views

听名字就可以看出,remote views是一种远程view,感觉有点像远程service,其实remote views是view的一个结构,他可以在其他的进程...

20670
来自专栏向治洪

Universal Image Loader for Android 使用实例

<span style="white-space:pre">      </span>// 1.获取ImageLoader实例         ImageLo...

254100

扫码关注云+社区

领取腾讯云代金券