正确的生命周期管理如何防止Android内存泄漏

OutOfMemoryException是一个常见的令人沮丧的错误,也是导致应用程序意外关闭的主要原因之一。

“如果应用程序昨天运行良好,为什么现在会发生这种情况?这个问题让Android的开发者和新手都感到困惑。

导致OutOfMemory异常的潜在原因有很多种,但其中最常见的是内存泄漏—应用程序中的内存分配从未释放。本文将解释如何通过有效的生命周期管理(开发过程中一个重要但经常被忽视的部分)来最小化这种风险。

为什么安卓系统会发生内存泄漏?

问题很简单。某些对象应该只有一个固定的寿命,当它们的使用寿命结束时,它们需要被删除。

理论上,当进程使用onStop或onDestroy终止时,应该处理该内存。但是,滥用对象引用可能会阻止垃圾收集器释放未使用的对象。例如:如果未使用的对象A引用了未使用的对象B,那么您将得到两个不必要的对象,垃圾回收器将永远不会释放它们,因为它们正在相互引用。

阻止内存泄漏这种情况发生的常见技巧

开发人员可以采取许多步骤来阻止死的活动被困在内存中。

  1. 在onResume()/onPause()或onStart()/onStop()中注册/注销广播接收器
  2. 不要对视图/活动/上下文使用静态变量
  3. 需要保存对上下文的引用的singleton应该使用applicationContext()或将其包装到WeakReference中
  4. 注意匿名和非静态内部类,因为它们包含对其封闭类的隐式引用。
  5. 如果要比父类(如处理程序)更长寿,请使用静态内部类而不是匿名类。
  6. 如果内部或匿名类是可取消的(如AsyncTask、Thread、RxSubscriptions),则在销毁活动时取消它。

Android生命周期感知组件

一旦你完成了上面的基本步骤,现在是时候做一些更重要的事情了:应用程序活动的生命周期。如果我们不能正确地管理生命周期,我们最终会在不再需要内存的时候挂掉它。

这涉及到许多不同的任务。对于每个活动,我们需要中断线程,去掉RxJava中的订阅,取消AsyncTask引用,并确保正确删除该活动的引用(以及与之相关的任何其他活动)。所有这些任务都会消耗开发人员的大量时间。

模型视图呈现器(MVP)使事情变得更加复杂,MVP是Android中构建用户界面的常用架构模式。然而,MVP对于从视图中分离业务逻辑非常有用。

在MVP模式中,View和Presenter都是它们之间行为契约的抽象实现。实现MVP最常见的方法是使用活动/片段作为视图的实现,并为习惯于引用视图的演示者使用简单的实现。

所以我们最终得到了一个带有Presenter引用的视图和一个带有视图引用的Presenter(提示:这里有一个潜在的漏洞)。

考虑到这些潜在的困难,我们有必要建立一个适当的管理结构来移除在生命周期中创建的多余内存。有几种行之有效的方法可以做到这一点:

1. 在Android Studio上使用Android Arch Lifecycle创建支持生命周期的组件

生命周期感知组件是智能的。例如,它们可以通过除去内存来对另一个组件(如活动或片段)的生命周期状态的更改作出反应。这意味着代码更轻,内存效率更高。

archlifecycle是Android的一个新库,它提供了一组工具来构建支持生命周期的组件。库以抽象的方式工作,这意味着生命周期所有者不再需要担心管理特定任务和活动的生命周期。

Arch生命周期的关键工具和定义如下:

  • 生命周期:一个排序系统,它定义了哪些对象具有Android生命周期,并允许对它们进行监视。
  • LifecycleObserver:一个常规接口,它监视每个被标识为具有Android生命周期的对象,使用一个简单的公式来处理每个密钥生命周期事件。
  • @OnLifecycleEvent:可以在实现LifecycleObserver接口的类中使用的注释。它允许我们设置关键生命周期事件,这些事件将在每次启动时触发带注释的方法。以下是可设置的所有事件的列表:ON_ANY、ON_CREATE、ON_DESTROY、ON_PAUSE、ON_RESUME、ON_START、ON_STOP
  • LifecycleOwner默认为每个可以管理其生命周期的Android组件实现,并让开发人员控制每个事件。

使用这些工具,我们可以将所有干净的任务发送给它们的所有者(在我们的例子中是演示者),这样我们就有了一个干净的、无泄漏的解耦代码(至少在演示者层是这样)。

下面是一个超级基本的实现,向您展示我们所说的:

interface View: MVPView, LifecycleOwner

class RandomPresenter : Presenter<View>, LifecycleObserver {
 private lateinit var view: View
 override fun attachView(view: View) {
  this.view = view
  view.lifecycle.addObserver(this)
 }

 @OnLifecycleEvent(Lifecycle.Event.On_DESTROY)
 fun onClear() {
	//TODO: clean 
}

2. 使用Android架构视图模型作为演示者和LiveData

另一种方法是通过使用新的生命周期组件来避免视图模型的内存泄漏。

ViewModel是一个抽象类,它实现一个称为onClear的函数,当必须删除某个特定对象时,该函数会自动调用。ViewModel是由框架生成的,它附加到创建者的生命周期中(作为一个额外的好处,使用Dagger注入非常容易)

除了使用ViewModel,LiveData还提供了一个重要的通信渠道。这意味着创造了一个容易观察到的反应性产物。

这里最重要的一点是,生命周期所有者可以观察到LiveData,因此数据传输总是由生命周期管理的,而且我们可以确保在使用它们时保留任何引用。

3. 使用LeakCanary和Bugfender

除了上述步骤之外,我们还想推荐两个重要的工具包:LeakCanary,一个用于监视泄漏的流行工具,以及我们自己的Bugfender。

LeakCanary是一个用于Android和Java的内存检测库。它是开源的,所以有一个庞大的社区支持它,它不仅仅告诉你一个漏洞,它还告诉你可能的原因。

我们的远程日志工具Bugfender允许您调试单个泄漏跟踪,并扩展一个名为DisplayLeakService的类,它让我们知道何时发生泄漏。然后我们就可以用Bugfender轻松登录了。

public class LeakUploadService extends DisplayLeakService {
 override fun afterDefaultHandling(heapDump: HeapDump, result: AnalysisResult, leakInfo: String) {
  if (result.leakFound) {
   Bugfender.d(“LeakCanary”, result.toString())
  }
 }
}

此外,用户还可以获得Bugfender的所有其他好处,包括全天候记录日志(即使设备离线)、内置故障报告和易于使用的web控制台。

以上就是Android内存泄漏的原因及解决技巧的详细内容,更多关于Android内存泄漏的资料请关注Devmax其它相关文章!

Android内存泄漏的原因及解决技巧的更多相关文章

  1. html5 canvas合成海报所遇问题及解决方案总结

    这篇文章主要介绍了html5 canvas合成海报所遇问题及解决方案总结,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  2. Html5 video标签视频的最佳实践

    这篇文章主要介绍了Html5 video标签视频的最佳实践,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  3. HTML5在微信内置浏览器下右上角菜单的调整字体导致页面显示错乱的问题

    HTML5在微信内置浏览器下,在右上角菜单的调整字体导致页面显示错乱的问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧

  4. ios – containerURLForSecurityApplicationGroupIdentifier:在iPhone和Watch模拟器上给出不同的结果

    我使用默认的XCode模板创建了一个WatchKit应用程序.我向iOSTarget,WatchkitAppTarget和WatchkitAppExtensionTarget添加了应用程序组权利.(这是应用程序组名称:group.com.lombax.fiveminutes)然后,我尝试使用iOSApp和WatchKitExtension访问共享文件夹URL:延期:iOS应用:但是,测试NSURL

  5. Ionic – Splash Screen适用于iOS,但不适用于Android

    我有一个离子应用程序,其中使用CLI命令离子资源生成的启动画面和图标iOS版本与正在渲染的启动画面完美配合,但在Android版本中,只有在加载应用程序时才会显示白屏.我检查了config.xml文件,所有路径看起来都是正确的,生成的图像出现在相应的文件夹中.(我使用了splash.psd模板来生成它们.我错过了什么?这是config.xml文件供参考,我觉得我在这里做错了–解决方法在config.xml中添加以下键:它对我有用!

  6. ios – 无法启动iPhone模拟器

    /Library/Developer/CoreSimulator/Devices/530A44CB-5978-4926-9E91-E9DBD5BFB105/data/Containers/Bundle/Application/07612A5C-659D-4C04-ACD3-D211D2830E17/ProductName.app/ProductName然后,如果您在Xcode构建设置中选择标准体系结构并再次构建和运行,则会产生以下结果:dyld:lazysymbolbindingFailed:Symbol

  7. Xamarin iOS图像在Grid内部重叠

    heyo,所以在Xamarin我有一个使用并在其中包含一对,所有这些都包含在内.这在Xamarin.Android中看起来完全没问题,但是在Xamarin.iOS中,图像与标签重叠.我不确定它的区别是什么–为什么它在Xamarin.Android中看起来不错但在iOS中它的全部都不稳定?

  8. ios – 为什么重复创建和删除SKShapeNode和SKNode导致内存泄漏?

    使用Xcode附带的spritekit模板,我修改场景如下:该应用程序似乎继续使用更多内存,直到它挂起或崩溃.使用泄漏和分配工具,我发现了以下内容:泄漏:分配:从图像中可以看出,存在大量使用内存的Malloc调用.我不直接调用Malloc–似乎这些调用是由SpriteKit完成的.同样,存在许多内存泄漏,这似乎也是由于SKShapeNode,SKNode或其他SpriteKit对象造成的.我如何解决或解决此内存(泄漏)问题?

  9. ios – Xcode显示内存泄漏,但仪器没有

    当我从Xcode运行我的应用程序时,很明显我有一个内存泄漏:当我提供一个自定义的ViewController时,内存增加,但是当我关闭它时,它不会退回.所以我也检查了使用仪器的分配工具,但这说明了一个不同的故事:可以看出,当我呈现ViewController时,仪器会显示尖峰,但是当内存使用被关闭时,内存使用率将恢复到以前的级别.我已经检查了我的代码至少15次,我个人无法找到任何内存泄漏,因此同意

  10. ios – 内存泄漏与UIWebView和Javascript

    清楚地包含一个Javascript文件到我的HTML是使UIWebView泄漏内存.当我重复使用相同的UIWebView对象时,或者每当我有内容实例化一个新的漏洞时,会出现泄漏的事实,导致我认为必须有一些JavaScript文件被loadHTMLString处理,导致泄漏.有人知道如何解决这个问题吗?

随机推荐

  1. Flutter 网络请求框架封装详解

    这篇文章主要介绍了Flutter 网络请求框架封装详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  2. Android单选按钮RadioButton的使用详解

    今天小编就为大家分享一篇关于Android单选按钮RadioButton的使用详解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧

  3. 解决android studio 打包发现generate signed apk 消失不见问题

    这篇文章主要介绍了解决android studio 打包发现generate signed apk 消失不见问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

  4. Android 实现自定义圆形listview功能的实例代码

    这篇文章主要介绍了Android 实现自定义圆形listview功能的实例代码,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  5. 详解Android studio 动态fragment的用法

    这篇文章主要介绍了Android studio 动态fragment的用法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  6. Android用RecyclerView实现图标拖拽排序以及增删管理

    这篇文章主要介绍了Android用RecyclerView实现图标拖拽排序以及增删管理的方法,帮助大家更好的理解和学习使用Android,感兴趣的朋友可以了解下

  7. Android notifyDataSetChanged() 动态更新ListView案例详解

    这篇文章主要介绍了Android notifyDataSetChanged() 动态更新ListView案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下

  8. Android自定义View实现弹幕效果

    这篇文章主要为大家详细介绍了Android自定义View实现弹幕效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  9. Android自定义View实现跟随手指移动

    这篇文章主要为大家详细介绍了Android自定义View实现跟随手指移动,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. Android实现多点触摸操作

    这篇文章主要介绍了Android实现多点触摸操作,实现图片的放大、缩小和旋转等处理,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

返回
顶部