摘要:2024年初,京东正式启动了鸿蒙 APP 的开发工作。由于电商 APP 大量依赖图片来展示商品信息,对图片库的性能和加载体验要求极高,因此图片库被作为核心基础能力提前纳入京东鸿蒙首期基础建设计划。本文将详细介绍京东自研鸿蒙图片库的开发过程及其技术原理。
基于 Taro 打造的京东鸿蒙 APP 已跟随鸿蒙 Next 系统公测,本系列文章将深入解析 Taro 如何实现使用 React 开发高性能鸿蒙应用的技术内幕
2024年初,京东正式启动了鸿蒙 APP 的开发工作。由于电商 APP 大量依赖图片来展示商品信息,对图片库的性能和加载体验要求极高,因此图片库被作为核心基础能力提前纳入京东鸿蒙首期基础建设计划。本文将详细介绍京东自研鸿蒙图片库的开发过程及其技术原理。
经过前期的调研,我们发现HarmonyOS平台的网络图片加载主要依赖以下两种实现方式:
仅仅提供基础的图片组件用于图片加载,但功能、图片格式支持和扩展性都较弱,无法实现更丰富的图片库能力。存在的一些问题:
社区参考Android图片库Glide的HarmonyOS版本实现,使用ArkTS开发。虽然能力比系统Image组件完善,但在性能、稳定性和扩展性都无法满足诉求。存在的一些问题:
性能一般代码质量一般,存在一些 bug 和 Crash整体架构、扩展性设计不够,无法加入更多的性能优化手段和扩展定制由于系统Image组件和ImageKnife开源库无法满足诉求,我们决定自主研发鸿蒙图片库。此外,随着HarmonyOS系统的引入,客户端在原有的iOS和Android基础设施上新增了一个平台,增加了维护成本。现有iOS/Android图片库也存在双端部分能力不一致的情况。集团内部期望未来的客户端基础设施能够支持跨端复用,以提高开发效率和一致性。
因此,团队选择基于C++为核心进行图片库开发,这种实现方式有以下优势:
跨端复用:将更多的公共模块下沉到C++层以实现跨端复用,未来图片库可以扩展到iOS和Android平台。适配 Taro:Taro Harmony框架基于鸿蒙CAPI进行开发,需要依赖CAPI的图片组件,可以避免ArkTS和C++之间频繁通信带来的性能损耗。高性能:C++在运行时性能上优于ArkTS。由于图片库使用C++进行跨端开发,面临不同平台之间的兼容性挑战,部分功能需要依赖于端侧的特定实现。为了应对这些复杂性,需要提供了一定的抽象能力,使得在支持不同平台时能够灵活调整和替换模块具体实现。在设计过程中也参考了iOS/Android业界成熟的开源库,如SDWebImage、Glide和Fresco。
我们选择采用模块化和架构分层的思想来设计图片库的整体架构。模块化将图片库拆分为多个独立模块,不仅增强了系统的灵活性和可替换性,还使我们能够在不同的客户端环境和图片加载场景下进行灵活调整和扩展。架构分层将图片库划分为Core层和客户端层,Core层使用C++进行开发支持跨端复用,客户端层用于特定模块的平台差异化实现。这种设计方法有效地解决了跨端开发的复杂性问题,提高了系统的可维护性和稳定性。
图片库主要分为图片缓存、解码器、图片源拉取、性能监控、图片组件这几个核心功能模块,模块之间不直接依赖可以被单独调用执行。
内存缓存:用于保存已解码后的位图对象,避免每次图片加载都要进行图片解码,从而提高加载性能。我们采用LRU算法实现来高效利用内存,同时提供了最大内存缓存大小和设备内存紧张时回收一部分图片缓存的策略,以动态调整内存消耗。磁盘缓存:用于保存下载后的网络图片在APP沙盒中,降低网络消耗并提高加载性能。提供了基础的图片读取、保存、删除、缓存大小读取等能力,同时支持多线程并行执行,实现图片磁盘缓存的高性能读写能力。图片数据源拉取模块负责图片数据源读取能力。我们在HarmonyOS平台上提供了多个数据源实现,处理不同格式的图片数据源拉取任务:
HTTP:提供HTTP链接的网络图片下载能力。底层使用Cornet进行实现,实现高性能的多请求并行网络下载能力,同时方便未来实现跨端复用。Base64:提供Base64格式的图片格式读取能力。图片解码器模块负责将编码后的图片格式解码为操作系统的图片格式用于显示。我们在HarmonyOS平台上提供了多个解码器实现处理不同格式的图片解码任务,可以支持多线程并行执行提高解码性能。
系统解码器:利用HarmonyOS系统提供的图片解码器可以支持PNG、JPG、GIF、WebP、SVG等常用图片的高性能硬件解码能力。AVIF 解码器:由于京东APP大量使用AVIF图片格式,通过集成libavif库支持AVIF图片的解码能力。加载性能监控:统计图片加载过程的各阶段耗时数据、缓存命中率、图片格式、资源消耗等信息,用来搭建图片加载性能数据平台和性能优化参考指标。异常监控:捕获图片加载过程中的各种错误异常,用来搭建图片加载线上异常告警和根据场景进行异常重试。图片组件基于系统Image组件进行封装,通过src属性传入解码后的PixelMap进行渲染。同时提供了一些额外的加载属性用于提升加载性能,例如添加lazy属性支持图片懒加载、sourceSize属性指定图片显示尺寸、 priority属性设置加载优先级。
图片加载流水线借鉴了Fresco的流水线设计。采用流水线方式可以灵活调整流水线的执行流程,可以通过搭配不同的流水线子任务以满足不同类型的图片加载任务和不同客户端的差异化诉求。同时也添加了很多优化策略提升优化图片加载流水线的执行性能。图片加载流水线主要包含以下这些能力:
京东图片服务器提供了多种处理功能,例如图片格式转换、图片降质、图片缩放、图片圆角、灰度图等。这些功能通过在图片URL中添加特定图片处理参数实现,图片服务器会根据参数设置提前将图片处理完成并保存到CDN服务器。
我们可以通过在流水线预处理阶段,针对京东域名图片自动追加特定的图片处理参数降低网络流量传输消耗,例如根据视图实际显示大小添加缩放参数,添加降质参数,使用.avif格式图片降低网络传输大小。同时在磁盘缓存模块实现中,我们也通过实现优化策略让部分相同的图片可以进行磁盘缓存复用避免重复下载。
质量保障作为一个新上线的基础组件,保证业务稳定性至关重要。为了快速发现并解决问题,图片库中实现了线上监控和异常恢复机制。
线上监控异常监控如前文所述,图片加载流水线涉及多个子任务,加载异常可能出现在任何一个环节。为了精准定位问题,图片库为每个子任务定制了不同的异常对象,每个异常对象包含独特的错误码,并会根据严重程度将其分为异常和警告两个级别。当加载流程结束时会根据上报策略进行异常上报。
性能监控除了加载成功率,加载速度也是图片库的核心指标,为了能正确还原加载流程,图片库按照配置策略记录每个子任务开始和结束时间,一方面用于统计各阶段的加载耗时,另一方面还作为异常定位时的重要辅助信息。
异常恢复除了从监控发现问题,为了将异常影响降至最低,图片库也实现了流水线失败重试、组件异常降级及线上配置降级三种异常恢复机制。
流水线失败重试在图片库任务预处理阶段,会基于配置策略对图片链接进行处理,如统一图片域名,图片格式转换等等。由于图片链接拼接规则复杂,无法保证所有链接进行转化处理后仍能正常加载,因此图片库流水线中增加了重试机制,会根据错误类型使用不同的重试策略。
组件异常降级对于经过重试仍然失败的任务,图片库组件侧会尝试直接使用系统Image组件进行兜底渲染,以防止出现图片库特定格式兼容性的问题。
此外,因为图片库流水线加载完成不意味着图片一定能正常渲染,图片的最终渲染成功与否取决于最终图片是否能在图片组件完成渲染上屏。因此,针对流水线成功但组件渲染失败的情况,图片库也会尝试降级到系统Image组件加载原始链接。
如果降级后仍然失败,则会按照业务配置顺序加载异常兜底图。
由于线上环境复杂,可能会出现仅发生在特定用户、系统版本、APP版本的异常,图片库也基于移动配置SDK支持了针对特定用户、机型、版本强制降级的能力。
加载对比未来规划网络优化:弱网优化、HTTPDNS 等策略优化图片网络下载性能。性能优化:提高磁盘缓存/内存缓存复用率、使用堆内存池减少堆内存分配、优化 GIF 播放、低端机优化等。适配京东图片服务器能力:利用服务器图片处理能力,如使用不同的缩放尺寸参数、清晰度、图片格式、图片域名等参数提高加载性能。能力完善:提供更多图片加载参数、支持更多图片类型等能力满足不同业务的加载诉求。更多平台支持:扩展到iOS、Android等更多平台。提升图片效果:使用不同的插值方式、超分技术、HDR 等能力提高图片显示效果。京东自研的鸿蒙图片库通过模块化设计和流水线调度策略,成功解决了跨端开发的复杂性问题,同时提高了系统的可维护性和稳定性。通过实现多重异常容错机制,保证了业务的稳定性。该图片库不仅满足了京东APP在鸿蒙系统上的高性能图片加载需求,还为未来的跨平台开发奠定了基础。
目前,图片库已通过Taro集成到京东鸿蒙 APP 中上线使用,在图片加载体验和稳定性上有不错的表现。未来,我们将继续优化图片库的性能,扩展功能,并探索在更多平台上的应用可能。同时,我们也会持续关注业界最新的图片处理技术,不断改进我们的解决方案,为用户提供更好的图片加载体验
来源:京东云开发者