热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

对于优化App内存方法你知道多少

本篇文章主要介绍Android开发中的部分知识点,通过阅读本篇文章,您将收获以下内容:一、App内存优化概述二、监视可用内存和内存使用情况三、合理的释放

本篇文章主要介绍 Android 开发中的部分知识点,通过阅读本篇文章,您将收获以下内容:
一、App内存优化概述
二、监视可用内存和内存使用情况
三、合理的释放内存
四、分析App需要用多少内存
五、使用内存优化框架
六、移除内存密集型资源,以及lib库

更多面试内容,面试专题,flutter视频 全套,音视频从0到高手开发。
关注GitHub:https://github.com/xiangjiana/Android-MS
免费获取面试PDF合集

一、App内存优化概述

随机存取存储器(RAM)在任何软件开发环境中都是非常有价值的资源,但对于物理内存经常受到限制的移动操作系统来说,它更有价值。尽管Android运行时(ART)Dalvik虚拟机都执行常规垃圾收集,但这并不意味着您可以忽略应用程序分配和释放内存的时间和位置。您仍然需要避免引入内存泄漏,这些通常由静态成员变量中的对象引用引起,并在生命周期回调定义的适当时间释放任何引用对象。

本页面介绍了如何主动减少应用程序中的内存使用量。有关Android操作系统如何管理内存的信息,请参阅Android内存管理概述

二、监视可用内存和内存使用情况

在修复解决APP中的内存使用问题之前,首先需要找到它们。 Android Studio中的内存分析器Memory Profiler可以帮助您通过以下方式查找和诊断内存问题:

1 . 查看App如何分配内存。

Memory Profiler显示了一个实时图,显示您的应用程序使用了多少内存,分配了Java对象的数量以及何时发生垃圾回收。

2. 记录GC快照

启动垃圾收集事件并在运行应用程序时抓取Java堆的快照。

3.记录您的应用程序的内存分配

然后检查所有分配的对象,查看每个分配的堆栈跟踪,然后跳转到Android Studio编辑器中的相应代码。

三、合理的释放内存

Android可以通过多种方式从您的应用程序中回收内存,或者在必要时将应用程序彻底关闭以释放内存以用于关键任务。为了进一步帮助平衡系统内存,避免系统需要终止应用程序进程,可以在Activity类中实现ComponentCallbacks2接口提供的onTrimMemory()回调方法,从而允许您的应用程序在处于前台或后台时侦听与内存相关的事件,然后释放对象以响应应用程序生命周期,或者指示系统需要回收内存的系统事件。

例如,您可以实现onTrimMemory()回调以响应不同的内存相关事件,如下所示

import android.content.ComponentCallbacks2;// Other import statements ...public class MainActivity extends AppCompatActivityimplements ComponentCallbacks2 {// Other activity code .../*** Release memory when the UI becomes hidden or when system resources become low.* @param level the memory-related event that was raised.*/public void onTrimMemory(int level) {// Determine which lifecycle or system event was raised.switch (level) {case ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN:/*Release any UI objects that currently hold memory.The user interface has moved to the background.*/break;case ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE:case ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW:case ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL:/*Release any memory that your app doesn't need to run.The device is running low on memory while the app is running.The event raised indicates the severity of the memory-related event.If the event is TRIM_MEMORY_RUNNING_CRITICAL, then the system willbegin killing background processes.*/break;case ComponentCallbacks2.TRIM_MEMORY_BACKGROUND:case ComponentCallbacks2.TRIM_MEMORY_MODERATE:case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:/*Release as much memory as the process can.The app is on the LRU list and the system is running low on memory.The event raised indicates where the app sits within the LRU list.If the event is TRIM_MEMORY_COMPLETE, the process will be one ofthe first to be terminated.*/break;default:/*Release any non-critical data structures.The app received an unrecognized memory level valuefrom the system. Treat this as a generic low-memory message.*/break;}}}

onTrimMemory() 回调方法是在Android 4.0时候添加的,之前版本请用onLowMemory()方法,跟TRIM_MEMORY_COMPLETE事件处理一样。

四、分析App需要用多少内存

为了允许多个正在运行的进程,Android为每个应用程序分配的堆大小设置了硬限制。确切的堆大小限制根据设备有多少总体可用RAM不同而有所不同。如果您的应用程序已达到堆容量并尝试分配更多内存,则系统将引发OutOfMemoryError

为了避免OutOfMemoryError内存不足,可以查询系统以确定当前设备上有多少可用的堆空间。你可以通过调用getMemoryInfo()来查询这个数字。这将返回一个ActivityManager.MemoryInfo对象,该对象提供有关设备当前内存状态的信息,包括可用内存,总内存以及内存阈值(即系统开始中断进程的内存级别)。 ActivityManager.MemoryInfo对象还暴露了一个简单的布尔值,lowMemory,可以判断你设备是否在低内存下运行。

如下例子,举例使用getMemoryInfo()

public void doSomethingMemoryIntensive() {// Before doing something that requires a lot of memory,// check to see whether the device is in a low memory state.ActivityManager.MemoryInfo memoryInfo = getAvailableMemory();if (!memoryInfo.lowMemory) {// Do memory intensive work ...}}// Get a MemoryInfo object for the device's current memory status.private ActivityManager.MemoryInfo getAvailableMemory() {ActivityManager activityManager = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();activityManager.getMemoryInfo(memoryInfo);return memoryInfo;}

五、使用内存优化框架

一些Android功能,Java类和代码构造倾向于使用比其他更多的内存。您可以通过在代码中选择更有效的替代方法来最大限度地减少应用程序使用的内存量

1. 谨慎使用Services

在不需要Services的情况下运行Services,是造成最严重的内存管理错误之一。
如果你的应用程序需要一个Services来在后台执行工作,那么除非它需要运行一个后台任务,否则不要让它保持运行。记得在完成任务时停止Services。否则,您可能会无意中造成内存泄漏。

当你启动一个Services时, 系统需要始终保持运行该Services的进程。此行为使得Services进程非常昂贵,因为Services使用的RAM对其他进程仍然不可用。这样可以减少系统在LRU缓存中保留的缓存进程的数量,从而降低应用程序切换的效率。内存不足时系统甚至可能导致系统崩溃,系统无法维护足够的进程来承载当前运行的所有服务。

您通常应该避免使用持久性Persistent Services,因为这些服务会常驻系统内存。相反,我们建议您使用诸如JobScheduler之类的替代实现。有关如何使用JobScheduler安排后台进程的更多信息,请参阅后台优化。

如果您必须使用服务,那么限制服务使用寿命的最好方法就是使用IntentService,一旦完成了处理启动它的意图,IntentService就会自动完成。有关更多信息,请阅读在后台服务中运行。

2.使用更优化的数据容器

编程语言提供的某些类未针对在移动设备上使用进行优化。例如,通用的HashMap实现可能是相当低效的内存,因为每个映射都需要单独的入口对象。

Android框架包括几个优化的数据容器,包括SparseArray,SparseBooleanArray和LongSparseArray。例如,SparseArray类更有效率,因为它们避免了系统需要自动复制密钥的情况,有时还需要创建另外一个或两个对象。

如有必要,您可以随时切换到原始数组以获得精简的数据结构。

3.使用nano protobufs进行序列化数据

协议缓冲区是一种语言中立,平台无关,可扩展的机制,由Google设计,用于序列化结构化数据 - 类似于XML,但更小,更快,更简单。如果你决定为你的数据使用protobufs,你应该总是在你的客户端代码中使用nano protobufs。经常protobufs生成非常详细的代码,这可能会导致您的应用程序中的许多种问题,如增加的RAM使用,APK大小增加,和较慢的执行。

有关更多信息,请参阅protobuf自述文件中的“Nano版本”部分。

4.避免内存泄漏

如前所述,垃圾收集事件通常不会影响您的应用程序的性能。但是,很多短时间内发生的垃圾收集事件可能会很快消耗掉你的帧时间。系统花费在垃圾收集上的时间越多,执行其他内容(如渲染或流式传输音频)的时间就越少。

内存流失通常会导致大量的垃圾收集事件发生。在实践中,内存流失描述了在给定的时间内发生的分配的临时对象的数量。

例如,您可以在for循环中分配多个临时对象。或者您可以在视图的onDraw()函数内创建新的PaintBitmap对象。在这两种情况下,应用程序都会以大批量快速创建大量对象。这些可能会迅速消耗年轻一代中的所有可用内存,从而迫使垃圾收集事件发生。

当然,你需要在你的代码中找到内存流失高的地方,然后才能修复它们。为此,您应该在Android Studio中使用Memory Profiler

六、移除内存密集型资源,以及lib库

你的代码中的一些资源和库可以在你不知道的情况下吞噬内存。您的APK的整体大小(包括第三方库或嵌入式资源)可能会影响您的应用消耗的内存量。您可以通过从代码中删除冗余,不必要或臃肿的组件,资源或库来改善应用程序的内存消耗。

1.减小APK的大小

您可以通过减少应用程序的整体大小来显着减少应用程序的内存使用量。比如:bitmap大小,res资源,动画帧数以及第三方库都可以影响APK的大小。 Android StudioAndroid SDK提供了多种工具来帮助您减少资源和外部依赖的大小。

有关如何减少您的整体APK大小的更多信息,请参阅缩小APK大小。

2.使用Dagger 2进行依赖注入

依赖注入框架可以简化您编写的代码,并提供适用于测试和其他配置更改的自适应环境。

如果您打算在应用程序中使用依赖项注入框架,请考虑使用Dagger 2. Dagger 2不使用反射来扫描您的应用程序的代码。Dagger的静态编译实现,意味着它可以在Android应用程序中使用,而无需增加运行成本或内存使用。

其他使用反射的依赖注入框架倾向于通过扫描代码来注释来初始化进程。这个过程可能需要更多的CPU周期和内存,并且在应用程序启动时会引起明显的滞后

3.谨慎使用外部库

外部库代码通常不是针对移动环境编写的,而且在用于移动客户端时可能效率低下。当您决定使用外部库时,您可能需要为移动设备优化该库。预先计划好这个工作,然后根据代码大小和内存占用情况来分析这个库,然后才决定使用它。

即使一些移动优化的库可能由于不同的实现而导致问题。例如,一个库可能使用nano protobufs,而另一个库使用微型protobufs,导致您的应用程序中有两个不同的protobuf实现。这可能发生在不同的日志记录,分析,图像加载框架,缓存以及许多您不希望的事情上。

尽管ProGuard可以帮助您使用正确的标志删除API和资源,但它不能删除库的大型内部依赖关系。您需要在这些库中的功能可能需要较低级别的依赖关系。如果库使用反射,这是常见的,并且意味着您需要花费大量时间手动调整ProGuard才能使用反射,那么当您从库中使用Activity子类时,这往往会产生大量的依赖关系工作等等。。

更多面试内容,面试专题,flutter视频 全套,音视频从0到高手开发。
关注GitHub:https://github.com/xiangjiana/Android-MS
免费获取面试PDF合集


推荐阅读
  • 目录实现效果:实现环境实现方法一:基本思路主要代码JavaScript代码总结方法二主要代码总结方法三基本思路主要代码JavaScriptHTML总结实 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 本文介绍了一个Java猜拳小游戏的代码,通过使用Scanner类获取用户输入的拳的数字,并随机生成计算机的拳,然后判断胜负。该游戏可以选择剪刀、石头、布三种拳,通过比较两者的拳来决定胜负。 ... [详细]
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • 使用Ubuntu中的Python获取浏览器历史记录原文: ... [详细]
  • 使用在线工具jsonschema2pojo根据json生成java对象
    本文介绍了使用在线工具jsonschema2pojo根据json生成java对象的方法。通过该工具,用户只需将json字符串复制到输入框中,即可自动将其转换成java对象。该工具还能解析列表式的json数据,并将嵌套在内层的对象也解析出来。本文以请求github的api为例,展示了使用该工具的步骤和效果。 ... [详细]
  • YOLOv7基于自己的数据集从零构建模型完整训练、推理计算超详细教程
    本文介绍了关于人工智能、神经网络和深度学习的知识点,并提供了YOLOv7基于自己的数据集从零构建模型完整训练、推理计算的详细教程。文章还提到了郑州最低生活保障的话题。对于从事目标检测任务的人来说,YOLO是一个熟悉的模型。文章还提到了yolov4和yolov6的相关内容,以及选择模型的优化思路。 ... [详细]
  • 本文介绍了使用kotlin实现动画效果的方法,包括上下移动、放大缩小、旋转等功能。通过代码示例演示了如何使用ObjectAnimator和AnimatorSet来实现动画效果,并提供了实现抖动效果的代码。同时还介绍了如何使用translationY和translationX来实现上下和左右移动的效果。最后还提供了一个anim_small.xml文件的代码示例,可以用来实现放大缩小的效果。 ... [详细]
  • VScode格式化文档换行或不换行的设置方法
    本文介绍了在VScode中设置格式化文档换行或不换行的方法,包括使用插件和修改settings.json文件的内容。详细步骤为:找到settings.json文件,将其中的代码替换为指定的代码。 ... [详细]
  • Nginx使用(server参数配置)
    本文介绍了Nginx的使用,重点讲解了server参数配置,包括端口号、主机名、根目录等内容。同时,还介绍了Nginx的反向代理功能。 ... [详细]
  • 如何用UE4制作2D游戏文档——计算篇
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了如何用UE4制作2D游戏文档——计算篇相关的知识,希望对你有一定的参考价值。 ... [详细]
author-avatar
企鹅
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有