Android 性能优化的重要性~

news/2024/11/17 22:22:15/

随着移动设备和应用程序市场不断发展,Android应用程序变得越来越多,对于开发者来说,他们必须使自己的应用程序与其他应用程序相比更加高效和快速,以吸引用户和确保业务成功。而Android用户期望应用程序如同其他设备上的应用程序一样快速且无卡顿。低效的Android应用程序会导致用户体验差,使得用户会寻找其他更好的应用程序。

所以就导致了,目前市场对于Android开发性能优化技术的要求越来越高,主要表现在以下几个方面:

  1. 减少应用启动时间和响应时间。由于用户对于应用启动时间和响应时间的要求越来越高,因此需要开发者使用一些技术手段来减少应用启动时间和响应时间,如使用启动器缓存、使用异步加载、使用线程池等。
  2. 减少内存使用和提高性能。由于内存使用过多会导致应用性能下降和应用崩溃,因此需要开发者开发一些能够减少内存占用的技术,如使用内存优化库、减少不必要的对象创建等。
  3. 减少电量消耗。由于电量是智能手机的一个重要指标,因此需要开发者使用一些优化技术来减少电量消耗,如使用节能模式、减少网络请求等。
  4. 加强网络连接和优化传输速度。 Android应用需要持续连接网络来获取数据,因此要求开发者对于应用中的网络连接进行优化,如使用https协议、减少请求次数等。

在面试中,不少公司都会拿性能优化相关问题作为面试题,去考察开发者们的功底水平,比如常见的问题有

1.如何评估应用程序的性能?
2.Android 应用程序开发中使用过哪些性能优化技术?
3.如何利用 Android Profiler 工具来检测性能问题?
4.如何使用 LeakCanary 检测内存泄漏的?
5.如何使用 Lint 工具来检测潜在的性能问题?
6.如何避免在应用程序中使用非必要的内存?
7.如何降低应用程序的启动时间?
8.如何降低应用程序的网络请求时间?
9.如何避免造成UI线程阻塞?
10.如何处理大型数据集和长列表的性能问题?
11.……

如果你是面试者,你都能对答如流吗?

如何避免造成UI线程阻塞?

这种是非常普遍的问题了。在 Android 应用开发中,UI 线程(也就是主线程)负责处理用户的交互操作、响应系统的事件和更新 UI 界面等任务。由于这些任务需要在非常短的时间内完成,因此任何 UI 线程上的耗时操作都可能导致整个应用程序变得缓慢或崩溃。

为了避免造成 UI 线程阻塞,我们可以采取以下策略

1. 使用异步任务

在 Android 应用程序中,异步任务是执行一些耗时的操作并在完成后返回结果的一个常用方法。你可以使用 AsyncTasK 类来创建一个异步任务。

使用异步任务的主要目的是将长时间运行的任务分配给一个后台线程,并保证在执行期间不会干扰主线程的上下文。值得注意的是,异步任务只应该用来处理那些不需要太多CPU时间的异步操作,否则会导致 CPU 利用率过高,也会导致其他线程受到影响。因此,异步任务最适合用于处理网络或磁盘 I/O 操作或者 CPU 密集型计算。

2. 使用线程池

在应用开发的过程中,我们经常需要在后台进行多个任务的执行,比如从网络下载文件、解析数据或者压缩图片等。如果每个任务都用新线程来执行,就会导致大量线程在应用中被创建和销毁,从而会给系统带来压力。为了避免这种情况,我们可以使用线程池来管理后台线程。

线程池在设计上是复用线程的机制,它可以控制最大并发线程数,从而避免创建过多线程导致系统资源的浪费。线程池可以通过 ThreadPoolExecutor 或者 Executors 工具类进行创建。在创建线程池时,我们可以调整 corePoolSize,maximumPoolSize,keepAliveTime 等参数,以达到最优的线程池配置。

3. 使用 Handler

handler 是 Android 系统提供的用于传递 Message 和 Runnable 对象的轻量级机制。在应用程序中,我们可以创建一个 Handler 实例,并使用它来将一些任务发布到消息队列中,然后在后台线程中进行处理。

在实现中,我们可以使用 Looper.getMainLooper() 方法来获取主线程的 Looper,然后在这个 Looper 上创建一个 handler 对象。最后,我们将处理器关联到主线程上,就可以使用 post 和 postDelay 等方法来在主线程以外的线程中提交消息了。

与异步任务一样,handler 本质上还是将一些耗时的操作放到了后台线程中执行,并保证在 UI 线程中不会阻塞。但是,在使用 handler 时需要注意的是,如果你在主线程中提交了过多的任务,就会导致系统内存不足,甚至会不可避免地导致应用程序的崩溃。因此,在使用 handler 时,我们需要尽量避免在主线程中过多地提交任务。

4. 延迟加载

如果一个页面或视图包含大量数据或资源,我们可以采取延迟加载的策略,将数据或资源的加载与显示分离出来,等用户滚动或其他事件触发时再显示。这种方法可以有效地避免首次加载时 UI 线程的阻塞。

对于 ListView、GridView 或者 RecyclerView 等包含大量视图的组件,我们可以使用 setOnScrollListener 或者 RecyclerView.OnScrollListener 等方法来实现数据的分批加载。

5. 使用缓存

缓存对于 Android 应用程序的性能影响很大。在移动应用程序中,网络是一个主要瓶颈。因此,在应用程序中,我们应该尽可能地减少网络请求。

为了避免从网络或者本地存储器中重复获取数据,我们可以使用缓存技术。缓存可以分为内存缓存和磁盘缓存两种。在内存缓存中,我们可以使用 LruCache 或者 SparseArray 等类库;在磁盘缓存方面,我们可以使用 DiskLruCache 库或者输出流和输入流来处理。

总结

避免 UI 线程的阻塞是 Android 开发中的重要问题。常见的解决办法包括使用异步任务、线程池和 handler 等机制,以及延迟加载和使用缓存来避免重复获取数据。尤其是对于多次网络请求和大量数据处理的场景,使用这些技术可以大大提高应用的性能和用户体验。

如何降低应用程序的启动时间?

应用程序的启动时间是影响用户体验的重要因素之一,因此在开发Android应用程序时,需要重视应用程序的启动时间。为了降低应用程序的启动时间,我们可以采取以下措施:

1. 延迟加载

延迟加载可以避免在启动时加载不必要的数据或资源。例如,我们可以使用懒加载机制,在需要的时候再加载Fragment或View,而不是在启动时就全部加载。我们还可以使用分页加载机制,例如,在首次加载数据时只加载前面几条数据,在用户滚动到页面底部时再加载下一页数据。

2. 使用Splash界面

Splash界面是一种在应用程序启动时显示的过渡界面,通常用于显示应用程序的LOGO或欢迎语言等信息。通过使用Splash界面,我们可以将一部分启动时间移动到Splash界面显示时间,从而减少在应用程序主界面加载时的等待时间。但需要注意的是,Splash界面的显示时间应该尽可能短,以免影响用户体验。

3. 优化布局

布局的复杂度会影响应用程序的启动时间,因此我们需要尽可能简化布局。例如,可以使用约束布局代替传统的相对布局,使用LinearLayout代替RelativeLayout。此外还可以通过减少布局的嵌套层数、移除不必要的布局以及使用include标签等方式来优化布局,从而减少启动时间。

4. 减少I/O操作

I/O操作是应用程序启动时间的一个重要瓶颈。我们可以通过缓存数据、减少数据库操作、使用缓存机制等方式减少I/O操作来降低应用程序的启动时间。

5. 优化图片

图片文件通常比较大,因此它们的加载时间会对应用程序的启动时间产生很大的影响。我们可以通过优化图片压缩、使用WebP格式图片、减少图片的数量等方式来减少图片加载时间。

6. 使用多进程

使用多进程可以将部分启动时间移至后台,从而减少应用程序启动时间。但需要注意的是,使用多进程会对系统资源产生一定的开销,因此不应该滥用。

7. 启动完毕后再处理数据

我们可以在应用程序启动之后再加载数据或执行复杂的操作,以避免在启动时出现等待时间。例如,我们可以使用异步任务或Handler等机制,在应用程序启动完成之后再执行数据加载或复杂操作。

综上所述,降低应用程序打开的时间可以从多方面入手:延迟加载、优化布局、减少I/O操作、优化图片、使用多进程、启动完毕后再处理数据。通过这些措施,可以显著减少应用程序的启动时间,提高用户体验。

通过上述两题就可以看出性能优化中含杂了不少知识点,而大部分的开发者对其只是了解过,并不熟知,回答上来只有一个大概,但如果问题在涉及的深入一点,比如到Framework 底层哪块的话,就有点懵了。如果想将你的应用优化到极致,底层的知识是必不可少的。

其实你也可以想一下,简单的优化操作你会大家肯定也会,并没有什么竞争力,而想要提升你的竞争优势,就只有提升你的技术水平,会别人所不会的,比如全面精通性能优化技能,深入到底层的那种。

当然如果想要精进,不仅要知道如何利用工具做性能优化,还要对底层原理充分了解,对架构设计有一定经验

这样才算精通对某个领域的性能优化,精通意味着

  1. 在面试环节,性能就是最好的面试题,既能考察候选人的潜力,也能考察其工程能力;

  2. 在大厂晋升中,其他部门的高级专家在不熟悉候选人业务的情况下,只能去考察底层的硬核知识,而性能问题又是最有区分度的问题

当然,在一些面试中,也会看到一些朋友**写“精通性能优化”,**但是让其描述,往往就是一些自己编写的业务,一些去除页面多余嵌套、使用线程池、ViewStub 这些非常浅的方案。

我们更希望能听到,线上复杂环境,低端机/弱网等因素下,用户触发的一系列的体验问题。

想要搞清楚这些,那么必须对底层原理有着深度了解,对各种case非常丰富的经验;很多人经常遇到措手不及的问题,大多是对出现问题的情况和处理思路模糊不清,导致此这种情况的出现就是因为没有搞懂底层原理。

为了帮助到大家更好的全面清晰的掌握好性能优化,准备了相关的学习路线以及核心笔记(还该底层逻辑):https://qr18.cn/FVlo89

性能优化核心笔记:https://qr18.cn/FVlo89

启动优化

内存优化

UI优化

网络优化

Bitmap优化与图片压缩优化https://qr18.cn/FVlo89

多线程并发优化与数据传输效率优化

体积包优化

《Android 性能监控框架》:https://qr18.cn/FVlo89

《Android Framework学习手册》:https://qr18.cn/AQpN4J

  1. 开机Init 进程
  2. 开机启动 Zygote 进程
  3. 开机启动 SystemServer 进程
  4. Binder 驱动
  5. AMS 的启动过程
  6. PMS 的启动过程
  7. Launcher 的启动过程
  8. Android 四大组件
  9. Android 系统服务 - Input 事件的分发过程
  10. Android 底层渲染 - 屏幕刷新机制源码分析
  11. Android 源码分析实战
  12. ……


http://www.ppmy.cn/news/42804.html

相关文章

亚马逊平台快速消耗滞销品的七大方式

一、亚马逊后台直接进行清仓 1、卖家和商品的资格 在管理多余库存页面上,可以查看亚马逊根据买家需求和其他因素推荐了哪些符合要求的商品参加清仓计划。商品当前价格下的消息将显示商品是否符合清仓促销要求(通过创建清仓促销提交)或清仓店铺要求(通过创建销售提…

【使用 HC-05 蓝牙、NRF24L01 和 HC-12 收发器模块的 Arduino 机器人汽车无线控制】

【使用 HC-05 蓝牙、NRF24L01 和 HC-12 收发器模块的 Arduino 机器人汽车无线控制】 1. 前言2. 使用HC-05蓝牙模块的Arduino机器人汽车控制3. 源代码3.1 HC-05 主代码:3.2 完整的HC-05从机代码:4. 使用智能手机和定制的Android应用程序控制4.1 Arduino机器人汽车4.2 完整的Ar…

C++基础回顾(上)

C基础回顾(上) 目录C基础回顾(上)前言关键字和标识符运算符数据类型函数类前言 C之前学过一点,但是很长时间都没用过,翻出了书从头看了一遍,简短地做了笔记,以便自己之后查看和学习…

如何在 Linux 中使用 Chage 命令,修改Linux系统用户密码更改策略

Chage是一个用于修改Linux系统用户密码更改策略的命令行工具。在本文中,我们将介绍如何在Linux系统中使用Chage命令。 检查用户密码过期信息 使用Chage命令可以检查用户密码更改策略和过期信息。要检查特定用户的密码过期信息,可以使用以下命令&#x…

WinForms 网格控件 - iGrid.NET 10.1.22 Crack

WinForms 网格控件 - iGrid.NET WinForms 的 10Tec 网格介绍 iGrid.NET 是适用于 Windows Forms 平台的多功能WinForms 网格控件,它是 Microsoft .NET Framework 和 .NET Core 的一部分。软件开发人员使用 iGrid for WinForms 来构建高度可调整的表格界面。它速度…

【数据库原理 • 三】关系数据库标准语言SQL

前言 数据库技术是计算机科学技术中发展最快,应用最广的技术之一,它是专门研究如何科学的组织和存储数据,如何高效地获取和处理数据的技术。它已成为各行各业存储数据、管理信息、共享资源和决策支持的最先进,最常用的技术。 当前…

【thingsboard+chirpstack 下行数据通信测试】

这里写目录标题 7. 节点未收到 tb 平台下发数据原因分析7.1 收到的size为07.2 节点收不到数据7.3 可以收到数据的一组例子7.4 节点没收到数据原因分析本文主要描述 tb 下发的数据,节点接收不到原因分析。 主要是数据格式以及解析脚本的对应关系 7. 节点未收到 tb 平台下发数据…

算法记录 | Day27 回溯算法

39.组合总和 思路: 1.确定回溯函数参数:定义全局遍历存放res集合和单个path,还需要 candidates数组 targetSum(int)目标和。 startIndex(int)为下一层for循环搜索的起始位置。 2.终止条件…