优化Android上的Java代码【笔记】

简介: 优化Android上的Java代码【笔记】

前言:代码优化并不是应用开发的首要任务,而提供良好的用户体验并专注于代码的可维护性才是首要的任务。

1.Android如何执行代码


Android平台将Java代码编译成Java字节码,并通过dex编译器将其编译成Dalvik字节码,最终交由Dalvik虚拟机(JVM是基于栈的虚拟机,而Dalvik是基于寄存器的虚拟机)执行。在Android 2.2之后,引入了Dalvik JIT(实时编译器),它把Dalvik字节码编译成本地代码,由于本地代码直接由CPU执行,而绕过了虚拟机,并且可以将本地代码为特定架构进行优化,所以可以明显加快执行速度。(在manifest.xml文件里可以用Android:vmSafeMode启用或禁用JIT编译器。默认是启用的)


2.将递归转为迭代(以斐波那契数列为例)


3.数据类型的修正


在Java中,long是64位、int是32位、short是16位。所有整数类型都是有符号的。如斐波那契数列第92项是超出Long型范围的,那么我们怎么办?Java中有个类——java.math.BigInteger。该对象可以可以容纳任意大小的有符号整数,该类定义了所有基本的数学运算。(Java.math包除了BigInteger还定义了BigDecimal参考,而java.lang.Math提供了数学常数和运算函数。如果应用不需要双精度,使用Android的FloatMath效果更佳)


4.使用BigInteger带来的问题


它有三大缺点:


(1)BigInteger是不可变的,例如a=a.add(b),而不能简单的写成a.add(b),所以每次都会创建一个新的BigInteger对象;


(2)BigInteger使用BigInt和本地代码实现,每分配一个BigInteger对象都会额外创建一个BigInt对象,从Java调用JNI调用本地代码会产生一定的开销;


(3)数字越大,相加运算花费的时间也越长。


5.通过优化算法来减少分配内存数量


尽管我们需要BigInteger来确保结果的正确性,但也不必使用BigInteger来计算所有的n值。既然基本类型long可以容纳小于等于92项的结果,可以混合BigInteger和基本类型。


通过优化算法的同时,还可以使用BigInteger实现的预分配对象,比如BigInteger.ZERO、BigInteger.ONE、BigInteger.TEN。


6.通过类的static代码来预先计算结果


但带来的缺点是可能会造成较大的内存使用


7.缓存先前的计算结果


如果计算的代价过高,最好把过去的结果缓存起来,下次就可以很快的取出来。比如Java中的HashMap就可以充当缓存,不过,Android定义了SparseArray类,当键是整数时,它比HashMap效率更高。因为HashMap使用的是java.lang.Integer对象,而SparseArray使用的是基本类型int。因此使用HashMap会创建很多的Integer对象。但是换句话说,尽管使用HashMap回避SparseArray慢一些,但这样的好处是可以让代码不依赖与Android平台。(Android定义了多种类型的稀疏数组:SparseArray[键为整数,值为对象]、SparseBooleanArray[键为整数,值为boolean]、SparseIntArray[键为整数,值为整数])

android.util.LruCache<K,V>,该类是Android3.1引入的,还可以自己通过继承java.util.LinkedHashMap,并覆写removeEldestEntry来实现类似的功能。

8.注意API的等级


试图调用不存在的API将导致应用崩溃,你通常可以使用Build.VERSION.SDK_INT获得Android平台的API等级。可是不幸的是,这个字段是在Android1.6(API等级为4)中引入的,所以如果你试图在早于其的版本中使用该字段,则会导致崩溃。另一种选择是使用Build.VERSION.SDK,它是API等级1引入的,但这一字段现在已经废弃,版本字符串也没有归档。

可以用反射来检查是否存在SDK_INT字段,即判断该平台是不是Android1.6或跟高版本,参见Class.forName("Android.os.Build$VERSION").getField("SDK"),反射技术也可以用来确认平台是否存在特定方法,参见Class.forName("XXX")和Class.getMethod(“XXX”)。不过使用反射会使代码变慢,因此在性能至关重要的地方应尽量避免使用反射。替代的方法是在静态初始化代码中调用以上方法以确认指定方法是否存在,在性能要求较高的地方只调用Method.invoke()就好了。

9.数据结构


Java.util包中常见的数据结构,在此基础之上,Android为了解决性能问题还增加了一些自身的实现:

LruCache\SparseArray\sparseBooleanArray\SparseIntArray\Pair

Java还定义了Array类和Collections类。这两个类只包含静态方法,分别操作数组和集合。例如,使用Array.sort对数组排序,使用Arrays.binarySearch在有序数组中搜索值。

每当需要选择一个数据结构来解决问题时,最好将选择范围缩小到只有几个类,因为通常每个类为特定目的或为特定的服务而优化。例如,如果你不需要在数据结构内部处理同步,应该选择ArrayList而不是Vector。如果你使用基于散列的数据结构(例如HashMap),而且键是自定义的对象,那么你需要确保正确地覆写了类定义中的equal和hashCode方法。hashCode的低劣实现可以轻易地将散列的收益化为乌有。可以参考这个 链接,里面有实现hashCode()的很好示例。

10.响应能力


应用的性能不仅仅在于速度,也要能让用户真正感觉到快才行。例如,显得更快的方法有,应用可以延迟创建对象,知道需要时才创建,成为推迟初始化的技术。另外,在开发过程中,你很有可能要在关注性能的地方侦测执行缓慢的代码。

@优化的基本原则是保持应用的持续响应,可以考虑使用多线程。

@优化Activity的启动或者销毁序列是非常重要的:当一个Activity被销毁时,并创建一个新实例,会调用以下序列:onPause\onStop\onDestroy\onCreate\onStart\onResume。应用可以在manifest.xml文件中指定每个Activity元素的Android:configChanges属性,让它只接受自己想处理的配置变化。这会导致调用Activity的onConfigurationChanged(),而不是销毁。

@由于内存分配需要花时间,等到对象真正需要使用时才进行分配,也是一个很好的选择。当某个对象并不是立即就要使用时,推迟创建对象有着很明显的好处。

10.1降低布局复杂性,加速资源文件的展开


(1)使用RelativeLayout代替嵌套LinearLayouts,尽可能保持“扁平化”的布局。此外减少创建的对象数量,也会让事件的处理速度加快。

(2)使用ViewStub推迟对象创建,它可以在运行时展开资源,当ViewStub需要展现时,它被相应的资源展开替换,自己就成为了等待垃圾回收的对象。


10.2 使用StrictMode检测不良行为


例如遇到了下列两种情况:

(1)网络很慢(服务器很久都没有响应)

(2)文件系统的访问速度很慢

结论就是,不应该在主线程中进行网络操作或访问文件系统。通常情况下,在应用启动时,即当onCreate被调用时,启用StrictMode, 参考、 参考2

Android 3.0中引入了需要特别留意的方法有detectCustomSlowCall()和noteSlowCall(),他们都是用来检测应用中执行缓慢的代码或潜在缓慢的代码。

10.3 SQLite的性能提升


(1)如果SQL语句是简单的字符串,需要解释或编译才可以执行,当你执行execSQL语句时,SQLite内部是编译执行的。而事实证明,执行SQLite语句可能需要相当长的一段时间。除了编译,语句本身可能还需要创建。由于String是不可改变的,这可能会遇到如之前所说的创建了过多的BigInteger对象的问题。如果我们想创建一个完整的数据库,则需要大量的增删改的操作,而每个INSERT语句都会创建一个String对象并调用execSQL,在内部进行解析。一个显而易见的优化方法是,加快要执行的SQL语句字符串的创建速度。在这种情况下,使用+运算符来连接字符串不是最有效的方法,而使用StringBuilder对象,或调用String.format可以提高性能。【它们只是优化了传递给execSQL的字符串创建速度,这两种方法并不算是与SQL相关的优化】

如果所有的INSERT语句都十分相似,那么我们就可以考虑使用compileStatement让语句在循环外只编译一次。由于只进行一次的语句编译,并且绑定值是比编译更轻量的操作,所以这种方法明显快多了。Android还提供了其他的API,使用ContentValue对象把值插入到数据库中,它基本上包含了列名和值之间的绑定信息,并通过调用db.insert()方法来实现插入。该方法是最快实现且最灵活的选择。【Android3.0的android.database和android.database.sqlite包发生了许多变化。例如,Activity类中的managedQuery、startManagingCursor和stopManagingCursor方法已经废弃,由CursorLoader取而代之】

Android还提供了一些可以提高性能的类。例如,可以使用DatabaseUtils.InsertHelper在数据库中插入多行,这样就只需编译一次INSERT语句。

(2)虽然以上的例子中并没有显式地创建任何事务,但会自动为每个插入操作创建一个事务,并在每次插入后立即提交。显式创建事务有以下两个基本特性:

【1】原子提交【2】性能更好

抛开对性能的追求,第一个特性是很重要的。原子提交意味着数据库的所有修改要么全都完成,要么全都不做。事务不会只提交部分修改。最重要的一点是,有些数据库不是保存在内存中,而是存储在持久性存储上(比如SD卡或内部闪存),众所周知,访问持久性存储比访问易失性记忆体慢得多,所以数据库工作的大量时间都花费在此,一次性事务是解决此类问题的较好办法,事务处理的优越性能够得到更显著的体现。

(3)我们可以使用限制数据库访问的方式来加快查询的速度。数据库查询仅会返回一个游标对象,然后用它来遍历结果。很明显如果查询时选择正确的参数,只读取需要的数据将使性能得到可观的提升,如果将所有行为作为一个事务处理则会更快,如果只需要一定数量的行,指定调用查询的限制参数,可以进一步减少数据库的访问时间。【还可以考虑使用SQLite的FTS(全文检索)扩展,它支持更多高级搜索特性(使用索引)。 参考】


目录
相关文章
|
2天前
|
消息中间件 Java 应用服务中间件
JVM实战—1.Java代码的运行原理
本文介绍了Java代码的运行机制、JVM类加载机制、JVM内存区域及其作用、垃圾回收机制,并汇总了一些常见问题。
JVM实战—1.Java代码的运行原理
|
10天前
|
传感器 监控 Java
Java代码结构解析:类、方法、主函数(1分钟解剖室)
### Java代码结构简介 掌握Java代码结构如同拥有程序世界的建筑蓝图,类、方法和主函数构成“黄金三角”。类是独立的容器,承载成员变量和方法;方法实现特定功能,参数控制输入环境;主函数是程序入口。常见错误包括类名与文件名不匹配、忘记static修饰符和花括号未闭合。通过实战案例学习电商系统、游戏角色控制和物联网设备监控,理解类的作用、方法类型和主函数任务,避免典型错误,逐步提升编程能力。 **脑图速记法**:类如太空站,方法即舱段;main是发射台,static不能换;文件名对仗,括号要成双;参数是坐标,void不返航。
34 5
|
16天前
|
人工智能 算法 Java
Java高级应用开发:AI赋能下的智能代码生成与优化
本文探讨了AI技术,特别是像DeepSeek这样的智能工具,在Java高级应用开发中的应用。AI在代码生成、优化、自动化测试等方面发挥重要作用,可自动生成高质量代码片段、提出优化建议并检测潜在错误,显著提升开发效率与代码质量。未来,AI将进一步推动Java开发的智能化和自动化,为开发者带来全新的开发体验。
|
16天前
|
人工智能 Java 数据处理
Java高级应用开发:基于AI的微服务架构优化与性能调优
在现代企业级应用开发中,微服务架构虽带来灵活性和可扩展性,但也增加了系统复杂性和性能瓶颈。本文探讨如何利用AI技术,特别是像DeepSeek这样的智能工具,优化Java微服务架构。AI通过智能分析系统运行数据,自动识别并解决性能瓶颈,优化服务拆分、通信方式及资源管理,实现高效性能调优,助力开发者设计更合理的微服务架构,迎接未来智能化开发的新时代。
|
1月前
|
JavaScript NoSQL Java
接替此文【下篇-服务端+后台管理】优雅草蜻蜓z系统JAVA版暗影版为例-【蜻蜓z系列通用】-2025年全新项目整合搭建方式-这是独立吃透代码以后首次改变-独立PC版本vue版搭建教程-优雅草卓伊凡
接替此文【下篇-服务端+后台管理】优雅草蜻蜓z系统JAVA版暗影版为例-【蜻蜓z系列通用】-2025年全新项目整合搭建方式-这是独立吃透代码以后首次改变-独立PC版本vue版搭建教程-优雅草卓伊凡
186 96
接替此文【下篇-服务端+后台管理】优雅草蜻蜓z系统JAVA版暗影版为例-【蜻蜓z系列通用】-2025年全新项目整合搭建方式-这是独立吃透代码以后首次改变-独立PC版本vue版搭建教程-优雅草卓伊凡
|
2月前
|
SQL Java 数据库连接
如何在 Java 代码中使用 JSqlParser 解析复杂的 SQL 语句?
大家好,我是 V 哥。JSqlParser 是一个用于解析 SQL 语句的 Java 库,可将 SQL 解析为 Java 对象树,支持多种 SQL 类型(如 `SELECT`、`INSERT` 等)。它适用于 SQL 分析、修改、生成和验证等场景。通过 Maven 或 Gradle 安装后,可以方便地在 Java 代码中使用。
455 11
|
2月前
|
JSON Java 数据挖掘
利用 Java 代码获取淘宝关键字 API 接口
在数字化商业时代,精准把握市场动态与消费者需求是企业成功的关键。淘宝作为中国最大的电商平台之一,其海量数据中蕴含丰富的商业洞察。本文介绍如何通过Java代码高效、合规地获取淘宝关键字API接口数据,帮助商家优化产品布局、制定营销策略。主要内容包括: 1. **淘宝关键字API的价值**:洞察用户需求、优化产品标题与详情、制定营销策略。 2. **获取API接口的步骤**:注册账号、申请权限、搭建Java开发环境、编写调用代码、解析响应数据。 3. **注意事项**:遵守法律法规与平台规则,处理API调用限制。 通过这些步骤,商家可以在激烈的市场竞争中脱颖而出。
|
3月前
|
缓存 算法 搜索推荐
Java中的算法优化与复杂度分析
在Java开发中,理解和优化算法的时间复杂度和空间复杂度是提升程序性能的关键。通过合理选择数据结构、避免重复计算、应用分治法等策略,可以显著提高算法效率。在实际开发中,应该根据具体需求和场景,选择合适的优化方法,从而编写出高效、可靠的代码。
69 6
|
3月前
|
安全 Java 编译器
深入理解Java中synchronized三种使用方式:助您写出线程安全的代码
`synchronized` 是 Java 中的关键字,用于实现线程同步,确保多个线程互斥访问共享资源。它通过内置的监视器锁机制,防止多个线程同时执行被 `synchronized` 修饰的方法或代码块。`synchronized` 可以修饰非静态方法、静态方法和代码块,分别锁定实例对象、类对象或指定的对象。其底层原理基于 JVM 的指令和对象的监视器,JDK 1.6 后引入了偏向锁、轻量级锁等优化措施,提高了性能。
101 3
|
3月前
|
前端开发 Java 测试技术
java日常开发中如何写出优雅的好维护的代码
代码可读性太差,实际是给团队后续开发中埋坑,优化在平时,没有那个团队会说我专门给你一个月来优化之前的代码,所以在日常开发中就要多注意可读性问题,不要写出几天之后自己都看不懂的代码。
90 2

热门文章

最新文章

  • 1
    Android历史版本与APK文件结构
  • 2
    【01】噩梦终结flutter配安卓android鸿蒙harmonyOS 以及next调试环境配鸿蒙和ios真机调试环境-flutter项目安卓环境配置-gradle-agp-ndkVersion模拟器运行真机测试环境-本地环境搭建-如何快速搭建android本地运行环境-优雅草卓伊凡-很多人在这步就被难倒了
  • 3
    【03】仿站技术之python技术,看完学会再也不用去购买收费工具了-修改整体页面做好安卓下载发给客户-并且开始提交网站公安备案-作为APP下载落地页文娱产品一定要备案-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
  • 4
    【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
  • 5
    【03】微信支付商户申请下户到配置完整流程-微信开放平台创建APP应用-填写上传基础资料-生成安卓证书-获取Apk签名-申请+配置完整流程-优雅草卓伊凡
  • 6
    【02】仿站技术之python技术,看完学会再也不用去购买收费工具了-本次找了小影-感觉页面很好看-本次是爬取vue需要用到Puppeteer库用node.js扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
  • 7
    Cellebrite UFED 4PC 7.71 (Windows) - Android 和 iOS 移动设备取证软件
  • 8
    escrcpy:【技术党必看】Android开发,Escrcpy 让你无线投屏新体验!图形界面掌控 Android,30-120fps 超流畅!🔥
  • 9
    Android实战经验之Kotlin中快速实现MVI架构
  • 10
    即时通讯安全篇(一):正确地理解和使用Android端加密算法
  • 1
    【03】微信支付商户申请下户到配置完整流程-微信开放平台创建APP应用-填写上传基础资料-生成安卓证书-获取Apk签名-申请+配置完整流程-优雅草卓伊凡
    66
  • 2
    android FragmentManager 删除所有Fragment 重建
    26
  • 3
    Android实战经验之Kotlin中快速实现MVI架构
    42
  • 4
    即时通讯安全篇(一):正确地理解和使用Android端加密算法
    42
  • 5
    escrcpy:【技术党必看】Android开发,Escrcpy 让你无线投屏新体验!图形界面掌控 Android,30-120fps 超流畅!🔥
    46
  • 6
    【01】噩梦终结flutter配安卓android鸿蒙harmonyOS 以及next调试环境配鸿蒙和ios真机调试环境-flutter项目安卓环境配置-gradle-agp-ndkVersion模拟器运行真机测试环境-本地环境搭建-如何快速搭建android本地运行环境-优雅草卓伊凡-很多人在这步就被难倒了
    161
  • 7
    Cellebrite UFED 4PC 7.71 (Windows) - Android 和 iOS 移动设备取证软件
    55
  • 8
    【03】仿站技术之python技术,看完学会再也不用去购买收费工具了-修改整体页面做好安卓下载发给客户-并且开始提交网站公安备案-作为APP下载落地页文娱产品一定要备案-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
    73
  • 9
    Android历史版本与APK文件结构
    183
  • 10
    【02】仿站技术之python技术,看完学会再也不用去购买收费工具了-本次找了小影-感觉页面很好看-本次是爬取vue需要用到Puppeteer库用node.js扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
    54