[译]内存泄露的八种花样,Android开发前景怎么样

除了这,让我们在我们的Activity类里在定义一个类,也就是内部类。为了提高代码的可读性和健壮性,封装程序逻辑,我们可能会这么做。如果我们创建了一个这样的内部类的实例,并通过静态变量持有了它,会怎样呢?你应该能猜到这又是一个内存泄露的点。

void createInnerClass() {
    class InnerClass {
    }
    inner = new InnerClass();
}

View icButton = findViewById(R.id.ic_button);
icButton.setOnClickListener(new View.OnClickListener() {
    @Override public void onClick(View v) {
        createInnerClass();
        nextActivity();
    }
});

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dDEkV7aW-1630589099064)(https://user-gold-cdn.xitu.io/2017/11/13/15fb35700988c536?imageView2/0/w/1280/h/960/ignore-error/1)]

内部类导致的内存泄露

不幸的是,由于内部类可以直接访问到它的外部类的变量,这个特性意味着内部类会隐式的持有一个对它的外部类的引用,这间接导致了我们不小心又泄露了Activity。

4. 匿名类

同样的,匿名类也持有一个指向它申明的地方所在的类的引用。如果你在Activity内定义和实例化一个AsyncTask匿名类,那也可能发生内存泄露

void startAsyncTask() {
    new AsyncTask<Void, Void, Void>() {
        @Override protected Void doInBackground(Void... params) {
            while(true);
        }
    }.execute();
}

super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
View aicButton = findViewById(R.id.at_button);
aicButton.setOnClickListener(new View.OnClickListener() {
    @Override public void onClick(View v) {
        startAsyncTask();
        nextActivity();
    }
});

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5uGsbzP0-1630589099066)(https://user-gold-cdn.xitu.io/2017/11/13/15fb3570043b3daf?imageView2/0/w/1280/h/960/ignore-error/1)]

AsyncTask的内存泄露

5. Handler

同样的原则也适用于后台任务:定义一个匿名的Runnable,然后将它加入Handler的处理队列里。这个Runnable对象会隐含的持有一个指向它定义的时候所在的Activity的引用,然后它会作为一个消息对象加入到Handler的消息队列里去。在Activity生命周期结束之后,只要这个消息还没被Activity处理,那就有一条引用链指向我们的Activity对象,使得Activity对象无法被回收,进而泄露。

void createHandler() {
    new Handler() {
        @Override public void handleMessage(Message message) {
            super.handleMessage(message);
        }
    }.postDelayed(new Runnable() {
        @Override public void run() {
            while(true);
        }
    }, Long.MAX_VALUE >> 1);
}


View hButton = findViewById(R.id.h_button);
hButton.setOnClickListener(new View.OnClickListener() {
    @Override public void onClick(View v) {
        createHandler();
        nextActivity();
    }
});

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lgnGYmt3-1630589099067)(https://user-gold-cdn.xitu.io/2017/11/13/15fb3570090ee02d?imageView2/0/w/1280/h/960/ignore-error/1)]

Handler导致的内存泄露

6. 线程

类似的问题我们可以在线程定时任务(TimerTask)里发现。

void spawnThread() {
    new Thread() {
        @Override public void run() {
            while(true);
        }
    }.start();
}

View tButton = findViewById(R.id.t_button);
tButton.setOnClickListener(new View.OnClickListener() {
  @Override public void onClick(View v) {
      spawnThread();
      nextActivity();
  }
});

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-b2Cb1bSp-1630589099068)(https://user-gold-cdn.xitu.io/2017/11/13/15fb357008f7f2d1?imageView2/0/w/1280/h/960/ignore-error/1)]

线程使用不当导致内存泄露

7. 定时任务

只要它们是通过匿名类的方式定义和实例化的,即便是工作在另外的线程,依旧会在Activity被destroy之后,存在一条指向Activity的引用链,导致Activity泄露。

void scheduleTimer() {
    new Timer().schedule(new TimerTask() {
        @Override
        public void run() {
            while(true);
        }
    }, Long.MAX_VALUE >> 1);
}

View ttButton = findViewById(R.id.tt_button);
ttButton.setOnClickListener(new View.OnClickListener() {
    @Override public void onClick(View v) {
        scheduleTimer();
        nextActivity();
    }
});

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rrr5crGm-1630589099070)(https://user-gold-cdn.xitu.io/2017/11/13/15fb357038002cf8?imageView2/0/w/1280/h/960/ignore-error/1)]

TimerTask导致的内存泄露

8. 系统服务

最后,还有一些系统服务可以通过上下文Context对象上的getSystemService)方法获取到。这些服务运行在他们各自的进程里,协助应用执行某种类型的的后台任务,或者和设备的硬件进行交互。如果Context对象需要系统服务内的某个事件发生的时候通知到这个Context,那么它需要把自身作为一个监听器注册给系统服务。系统服务也由此持有了一个对Activity对象的应用。如果我们在Activity的生命周期结束的时候忘了去反注册这个监听器,就会发生泄露。

void registerListener() {
       SensorManager sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
       Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ALL);
       sensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_FASTEST);
}

View smButton = findViewById(R.id.sm_button);
smButton.setOnClickListener(new View.OnClickListener() {
    @Override public void onClick(View v) {
        registerListener();
        nextActivity();
    }
});

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-s1pGOHOP-1630589099071)(https://user-gold-cdn.xitu.io/2017/11/13/15fb357037cc1204?imageView2/0/w/1280/h/960/ignore-error/1)]

传感器管理器导致的内存泄露

最后

总之啊,家里没矿的同学们,如果你们想以后的日子过得好一些,多想想你们的业余时间怎么安排吧;

技术方面的提升肯定是重中之重,但是技术外的一些“软实力”也不能完全忽视,很多时候升职确实是因为你的技术足够强,但也与你的“软实力”密切相关

在这我也分享一份大佬自己收录整理的 Android学习PDF+架构视频+面试文档+源码笔记 ,还有高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料这些都是我闲暇还会反复翻阅并给下属员工学习的精品资料。在脑图中,每个知识点专题都配有相对应的实战项目,可以有效的帮助大家掌握知识点。

总之也是在这里帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习

CodeChina开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》](https://codechina.csdn.net/m0_60958482/android_p7)**

[外链图片转存中…(img-Jcwr8tmx-1630589099072)]

[外链图片转存中…(img-62d9Y9ts-1630589099072)]

相信自己,没有做不到的,只有想不到的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值