写点什么

[译] 内存泄露的八种花样,app 优化的内容及策略

用户头像
Android架构
关注
发布于: 21 分钟前

view = findViewById(R.id.sv_button);}


View svButton = findViewById(R.id.sv_button);svButton.setOnClickListener(new View.OnClickListener() {@Override public void onClick(View v) {setStaticView();nextActivity();}});



静态 View 内存泄露


等下!看到没。你知道一个 attach 了的 view 内部会持有一个指向 Context 的引用,换句话说,那就是我们的 Activity。通过吧一个 View 设为静态变量,我们创建了一个能长期持有 Activity 的引用链,导致 Activity 被泄露了。千万不要把 attach 的 view 设为静态变量,如果实在必须这么做,至少保证在 Activity 的生命周期结束前把它从 View 的层级结构里[detach](


))掉。

3. 内部类

除了这,让我们在我们的 Activity 类里在定义一个类,也就是[内部类](


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


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


View icButton = findView


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


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



内部类导致的内存泄露


不幸的是,由于内部类可以直接访问到它的外部类的变量,这个特性意味着内部类会隐式的持有一个对它的外部类的引用,这间接导致了我们不小心又泄露了 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();}});



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();}});



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();}});



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

7. 定时任务

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
[译]内存泄露的八种花样,app优化的内容及策略