五分钟体验内存泄露检测LeakCanary

作者: 我在等你回复可你没回 | 来源:发表于2017-02-25 21:37 被阅读4037次

    昨天感冒,大晚上10点就睡了,本来今天打算休息养伤的,谁知道大下午4点的时候传来噩耗有必解bug,只能顶着伤病来到公司了。废话少说了,今天咱们来体验一下LeakCanary的内存检测功能啦。LeakCanary这个库咋用啊,调用肯定是很简单啦,在Application类里面调用一下LeakCanary.install(this);就完事了,所以说搞应用是真他妈的简单。下面五分钟计时开始!

    1.下载工程,工程的github网址:https://github.com/square/leakcanary 又是square公司的,记住这个公司,这个公司太牛逼了,什么okhttp,rxjava都是这公司搞的,就没见中国有什么创造。

    网址.png

    2.导入到Android studio中去,导入后是这个狗样

    Android studio.png

    3.然后编译了,有时会报sdk不在,你就下载sdk嘛,有时还会报下面

    Error:(21, 0) CreateProcess error=2, 系统找不到指定的文件。 <a href="openFile:D:\androidstdioSDK\workspace\leakcanary\leakcanary-android\build.gradle">Open File</a>
    

    貌似是要配git的环境变量,我懒得配,直接把这句还有java中引用的地方通通删掉,就向下图

    通通删掉.png

    4.然后假设你编译过了,编译不过你找我。开始执行,会给你装两个apk,分别来自leakcanary-sample和leakcanary-android文件夹
    安装后是这个鸟样。

    两个apk.png

    然后打开左边LeakCanarySample那个apk,英文看的懂不?看不懂就别看了,这篇文章也别看了,英语都不会,还是中国人吗?英文意思,就是让你点下那个按钮,然后旋转一下屏幕。然后过个5秒,会提示了泄露了!!在状态栏可以看到,然后点一下,就会跳到上图的第二个apk去展示。

    apk.png 通知栏.png

    第一次运行可能通知栏提醒了给他个写存储的权限,那就给嘛。

    权限.png

    例子程序是下面这样的,有心的人可以看下他是怎么泄露的,反正我不知道,我就是一把梳,就是干

    public class MainActivity extends Activity {
    
      @Override protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_activity);
    
        View button = findViewById(R.id.async_task);
        button.setOnClickListener(new View.OnClickListener() {
          @Override public void onClick(View v) {
            startAsyncTask();
          }
        });
      }
    
      void startAsyncTask() {
        new AsyncTask<Void, Void, Void>() {
          @Override protected Void doInBackground(Void... params) {
            // Do some slow work in background
            SystemClock.sleep(20000);
            return null;
          }
        }.execute();
      }
    }
    

    看样子是有个匿名内部类AsyncTask造成的,匿名内部类持有外部类的引用,外部类是MainActivity ,MainActivity 调用destory的时候,AsyncTask还在干活呢,不能释放,AsyncTask不能释放,MainActivity 你就别想释放。然后现象就是MainActivity 调用destory后,MainActivity 对象还在内存死皮赖脸的活着,官方用语就是MainActivity 对象泄露了。

    至于检测原理,搞应用的话,就不用知道了,调调api就用了,想这么多又不会加人工,是不是?开玩笑,简单说一下。我接单造个轮子你就知道了,十多行代码就搞定了,甚至有时我觉得你根本就不需要这个库,自己造个轮子就好。
    按照我的理解,我要造这个轮子的话,是这样子造的,在activity的ondestory方法里面实现

      @Override
      protected void onDestroy() {
        super.onDestroy();
       // 开启一个后台线程,这个线程不要持有activity的应用,不然泄露又说怪这个线程
       Thread detectThread=new DetectThread("detectThread");
        //用一个弱引用指向这个activity,并且关联到弱引用序列,我的意思是关联。怎么关联法?这个是java的基础,你去搜下WeakReferenceQueue ,当WeakReference所指对象没有强引用时,WeakReference就是被放到这个WeakReferenceQueue 序列
      WeakReferenceQueue queue=new WeakReferenceQueue();
       WeakReference<Activity> weakref=new WeakReference(this,queue);
       detectThread.start();//开始检查
      }
    

    在另一个文件定义DetectThread

    class DetectThread extend Thread {
           sleep(5000);//睡个5秒去检测
           gc();   //回收下垃圾先
          if(queue.contains(weakref)){
             Log.i(tag,"没有泄露,做的很好");
          }else{
            Log.i(tag,"泄露了傻逼!!!");
           }
    }
    

    基本原理太简单了,就是新建一个WeakReference对象指向要关注的Activity,Activity被回收的时候WeakReference对象会加到WeakReferenceQueue 队列中,检测WeakReferenceQueue队列 是否有WeakReference对象就知道有没有泄露了,有的话就没有泄露,没有的话就他妈泄露了。WeakReferenceQueue 的这一特性自己百度去,这是java基础,基础,基础!!!!!

    至于真实源代码,下节我再告诉你!!其实跟我造的轮子差不多。如果我先写的话,说不定我就不开源,收费使用!!!

    加班没有加班费又没有加班零食,能不能打赏我几毛钱买个烧饼?

    相关文章

      网友评论

      本文标题:五分钟体验内存泄露检测LeakCanary

      本文链接:https://www.haomeiwen.com/subject/vpynwttx.html