HarmonyOS鸿蒙Next中如何处理低内存设备上的资源加载?

HarmonyOS鸿蒙Next中如何处理低内存设备上的资源加载? 应用要展示超大高清地图图块(比如 8000x6000 像素),在低端鸿蒙设备上直接加载会 OOM。系统有没有提供按区域解码或流式加载图片的能力?

8 回复

图片资源加载优化

在应用开发中,当图片资源数量或大小超过特定阈值时,由于图片资源的格式需要通过CPU解压缩为纹理格式才能直接被GPU读取,将增加CPU的处理时间,导致图片加载延迟。此外,CPU解压缩生成的图片资源会占用大量内存空间,增加内存压力,可能导致卡顿和掉帧。本文从预置图片与非预置图片两个方面介绍图片资源加载优化方案。其中,预置图片主要通过纹理压缩技术进行优化;非预置图片资源则包括使用图像编辑工具压缩、降低GIF图片分辨率、优化网络图片资源、优先使用.webp图片,利用autoResize对图片资源进行降采样等优化策略。

预置图片资源加载优化

预置图片资源是指打包在应用安装包内的本地图片,存放于‘resource/base/media’目录下。开发者可通过纹理压缩对预置图片资源进行加载优化。

纹理压缩

纹理压缩用于减小纹理图片文件大小,通过纹理压缩技术,在构建过程中对预置图片进行转码和压缩,从而减少CPU的处理时间,降低内存占用,提升应用性能。

实现原理

预置图片在不使用纹理压缩时,需要先经CPU解码生成PixelMap,再上传给GPU生成纹理。此过程耗时较长。开发者可使用纹理压缩技术,在编译构建阶段提前完成CPU解码和纹理生成,以减少CPU处理图片的时间。纹理压缩需在编译文件中配置相关属性,构建时根据配置找到预置图片,转换生成纹理码流,并进行超压缩编码生成超压缩码流。编译完成后进入运行态,进行超压缩解码生成纹理码流,GPU读取纹理码流后进行渲染显示。

cke_575.png

纹理压缩在编译构建中对预置图片进行处理。首先在编辑器的编译文件中配置纹理压缩参数。根据配置参数,hvigor读取待压缩的文件资源,构造restool命令解析并生成资源文件列表。然后遍历文件列表,将待转换文件转码为纹理格式。已转换的资源文件不再打包到构建产物中。最后将纹理文件和未转换的文件一起构建生成资源产物。

编译构建资源文件开启纹理压缩时序图如下:

cke_1264.png

非预置图片资源加载优化

非预置图片不是应用内的资源,而是通常来自网络或本地文件系统。这类图片一般不是固定不变的,例如:用户头像、动态内容中的图片、从服务器获取的商品图片等。本章节将从图片使用前和使用中两个层面介绍几种常见的非预置图片资源加载优化方案,具体如下。

  • 优化使用前的图片资源: 预压缩到实际UI尺寸,包括使用图像编辑工具压缩、GIF图片降低分辨率;

    使用CDN优化网络图片资源;

    优先使用.webp图片。

  • 优化使用中的图片资源: 使用autoresize对Image组件进行降采样。

使用图像编辑工具压缩

在应用构建前,建议使用图片编辑工具或脚本,将图片分辨率调整为UI中的实际显示大小,并进行适当的压缩编码,以减小资源体积、提升加载性能。

GIF图片降低分辨率

通过使用FFmpeg三方库的能力降低分辨率,有以下两种方式实现GIF图片的压缩(也可将两种方式进行结合)。

使用-s设置图片的分辨率,例如,将一个GIF图片的分辨率降低,宽高设置为90x90像素,可以使用如下命令:

  1. ffmpeg -i input.gif -s 90x90 -y output.gif (设置宽高均为90像素)

或者使用-vf参数配合scale过滤器,设置宽为90像素,高度自动等比例缩放。

  1. ffmpeg -i input.gif -vf “scale=90:-1” -y output.gif

以上命令的参数的意义如下:

  • -s 90x90:设置图片分辨率为90x90像素。
  • -y:覆盖已有文件。
  • -vf “scale=90:-1”:设置图片滤镜,参数是单个滤镜或多个逗号分隔的滤镜链。

优先使用.webp图片

.webp格式支持有损和无损压缩,其优势在于显著减少文件大小,同时保持高质量图像传输,是一种功能全面、适用于多种场景的图像格式。

表1 .webp相较于.png和.jpg的优势

优势 说明 适用场景
更小的文件体积、更快加载、节省宽带 同质量下比.jpg小25%~35%,比.png小25% 网站图片
支持透明通道 .png也支持,但.webp体积更小 UI图标、按钮、透明图
支持动画 可替代.gif,质量更高、体积更小 动画表情包

使用autoResize对Image组件进行降采样

autoResize适用于需要组件尺寸动态适配的场景。例如,在响应页面内容变化或设备形态差异(如不同屏幕尺寸、折叠屏展开/收起)时,图片需要根据父容器尺寸自动缩放,使用autoResize可避免图片溢出或留白,提升界面自适应能力。通过给Image组件设置autoResize为true时,组件会根据显示区域的尺寸决定用于绘制的图源尺寸,有利于减少内存占用。

Image(this.imageUrl)
  .width(300)
  .height(200)
  .autoResize(true)

总结

根据图片资源是否预置(即打包在应用内),优化策略有所不同。对于预置图片,推荐开发者使用纹理压缩技术。对于非预置图片,可采用预压缩至实际UI尺寸、网络图片资源优化、GIF图片压缩、优先使用.webp图片等方式对使用前的图片进行优化;通过autoResize对使用中的图片进行优化。开发者需根据实际情况,选择合适方案或方案组合对图片资源进行性能优化。

更多关于HarmonyOS鸿蒙Next中如何处理低内存设备上的资源加载?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


鸿蒙的 Image 组件不直接支持区域解码,但可通过以下方式优化:

  • 使用 imageSource.createImageSource() + pixelMap 分块读取(需图片格式支持,如 JPEG);
  • 将大图切分为小瓦片(tiles),按视口动态加载;
  • 启用 ImageobjectFit: ImageFit.Containalt 占位图,避免主线程阻塞;
  • 结合 TaskPool 在后台预解码下一屏图像。

1.参考这个看看可有帮助:

  1. 图像分块切割 将原始大图分割为等尺寸的小瓦片(如256x256像素),每块瓦片独立存储。

官网瓦片图层参考: https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/map-tile

瓦片图

如何通过命令行查看 Linux 系统信息

查看系统版本信息

1. 查看内核版本

uname -r

2. 查看系统发行版本

cat /etc/os-release

查看硬件信息

1. 查看 CPU 信息

lscpu

2. 查看内存信息

free -h

3. 查看磁盘信息

df -h

查看网络信息

1. 查看 IP 地址

ip addr show

2. 查看网络连接

netstat -tulpn

查看进程信息

1. 查看运行中的进程

ps aux

2. 查看系统负载

top

查看用户信息

1. 查看当前登录用户

who

2. 查看用户组

cat /etc/group

查看系统运行时间

uptime

查看系统日志

1. 查看系统日志

journalctl -xe

2. 查看安全日志

cat /var/log/secure

查看环境变量

env

查看系统服务状态

systemctl status

查看已安装的软件包

1. 对于基于 Debian 的系统

dpkg -l

2. 对于基于 Red Hat 的系统

rpm -qa

查看系统架构

arch

查看 SELinux 状态

sestatus

查看防火墙状态

1. 对于 firewalld

firewall-cmd --state

2. 对于 iptables

iptables -L

查看系统时间

date

查看时区设置

timedatectl

查看系统语言设置

locale

查看系统主机名

hostname

查看系统重启记录

last reboot

查看内核参数

sysctl -a

查看系统中断信息

cat /proc/interrupts

查看系统内存映射

cat /proc/meminfo

查看系统交换空间

swapon -s

查看系统模块信息

lsmod

查看系统设备信息

lspci

查看 USB 设备信息

lsusb

查看系统温度

sensors

查看系统电源状态

acpi -V

查看系统声音设备

aplay -l

查看系统显卡信息

lspci | grep -i vga

查看系统声卡信息

lspci | grep -i audio

查看系统网络设备

lspci | grep -i network

查看系统存储设备

lspci | grep -i storage

查看系统 RAID 信息

cat /proc/mdstat

查看系统 LVM 信息

lvdisplay

查看系统文件系统类型

df -T

查看系统挂载点

mount | column -t

查看系统打开文件

lsof

查看系统资源限制

ulimit -a

查看系统内核消息

dmesg

查看系统启动消息

cat /var/log/boot.log

查看系统认证日志

cat /var/log/auth.log

查看系统邮件日志

cat /var/log/maillog

查看系统 cron 日志

cat /var/log/cron

查看系统 yum 日志

cat /var/log/yum.log

查看系统 apt 日志

cat /var/log/apt/history.log

查看系统 dpkg 日志

cat /var/log/dpkg.log

查看系统 X11 日志

cat /var/log/Xorg.0.log

查看系统 lightdm 日志

cat /var/log/lightdm/lightdm.log

查看系统 gdm 日志

cat /var/log/gdm/:0.log

查看系统 kdm 日志

cat /var/log/kdm.log

查看系统 sddm 日志

cat /var/log/sddm.log

查看系统 wayland 日志

cat /var/log/wayland.log

查看系统 pulseaudio 日志

cat /var/log/pulseaudio.log

查看系统 alsa 日志

cat /var/log/alsa.log

查看系统 bluetooth 日志

cat /var/log/bluetooth.log

查看系统 networkmanager 日志

cat /var/log/NetworkManager.log

查看系统 wpa_supplicant 日志

cat /var/log/wpa_supplicant.log

查看系统 dhclient 日志

cat /var/log/dhclient.log

查看系统 sshd 日志

cat /var/log/sshd.log

查看系统 vsftpd 日志

cat /var/log/vsftpd.log

查看系统 apache 日志

cat /var/log/apache2/access.log

查看系统 nginx 日志

cat /var/log/nginx/access.log

查看系统 mysql 日志

cat /var/log/mysql/error.log

查看系统 postgresql 日志

cat /var/log/postgresql/postgresql-12-main.log

查看系统 mongodb 日志

cat /var/log/mongodb/mongod.log

查看系统 redis 日志

cat /var/log/redis/redis-server.log

查看系统 docker 日志

cat /var/log/docker.log

查看系统 kubernetes 日志

cat /var/log/kubernetes/kubelet.log

查看系统 openshift 日志

cat /var/log/openshift/openshift.log

查看系统 systemd 日志

journalctl -u systemd

查看系统 audit 日志

cat /var/log/audit/audit.log

查看系统 faillog 日志

cat /var/log/faillog

查看系统 lastlog 日志

cat /var/log/lastlog

查看系统 wtmp 日志

cat /var/log/wtmp

查看系统 btmp 日志

cat /var/log/btmp

查看系统 utmp 日志

cat /var/log/utmp

查看系统 sulog 日志

cat /var/log/sulog

查看系统 xferlog 日志

cat /var/log/xferlog

查看系统 proftpd 日志

cat /var/log/proftpd/proftpd.log

查看系统 pure-ftpd 日志

cat /var/log/pure-ftpd/pure-ftpd.log

查看系统 vsftpd 日志

cat /var/log/vsftpd.log

查看系统 samba 日志

cat /var/log/samba/log.smbd

查看系统 squid 日志

cat /var/log/squid/access.log

查看系统 bind 日志

cat /var/log/bind/bind.log

查看系统 postfix 日志

cat /var/log/postfix/maillog

查看系统 sendmail 日志

cat /var/log/sendmail.log

查看系统 exim 日志

cat /var/log/exim/mainlog

查看系统 dovecot 日志

cat /var/log/dovecot/dovecot.log

查看系统 courier 日志

cat /var/log/courier/courier.log

查看系统 cyrus 日志

cat /var/log/cyrus/cyrus.log

查看系统 openldap 日志

cat /var/log/openldap/openldap.log

查看系统 sssd 日志

cat /var/log/sssd/sssd.log

查看系统 kerberos 日志

cat /var/log/kerberos/krb5.log

查看系统 pam 日志

cat /var/log/pam.log

查看系统 sudo 日志

cat /var/log/sudo.log

查看系统 su 日志

cat /var/log/su.log

查看系统 login 日志

cat /var/log/login.log

查看系统 logout 日志

cat /var/log/logout.log

查看系统 acpid 日志

cat /var/log/acpid.log

查看系统 avahi 日志

cat /var/log/avahi/avahi.log

查看系统 dbus 日志

cat /var/log/dbus/dbus.log

查看系统 gdm 日志

cat /var/log/gdm/:0-greeter.log

查看系统 lightdm 日志

cat /var/log/lightdm/lightdm-greeter.log

查看系统 sddm 日志

cat /var/log/sddm-greeter.log

查看系统 xsession 日志

cat /var/log/xsession-errors

查看系统 xorg 日志

cat /var/log/Xorg.0.log

查看系统 wayland 日志

cat /var/log/wayland.log

查看系统 gnome 日志

cat /var/log/gnome-session/gnome-session.log

查看系统 kde 日志

cat /var/log/kde-session/kde-session.log

查看系统 xfce 日志

cat /var/log/xfce-session/xfce-session.log

查看系统 lxde 日志

cat /var/log/lxde-session/lxde-session.log

查看系统 mate 日志

cat /var/log/mate-session/mate-session.log

查看系统 cinnamon 日志

cat /var/log/cinnamon-session/cinnamon-session.log

查看系统 budgie 日志

cat /var/log/budgie-session/budgie-session.log

查看系统 pantheon 日志

cat /var/log/pantheon-session/pantheon-session.log

查看系统 deepin 日志

cat /var/log/deepin-session/deepin-session.log

查看系统 unity 日志

cat /var/log/unity-session/unity-session.log

查看系统 enlightenment 日志

cat /var/log/enlightenment/enlightenment.log

查看系统 fluxbox 日志

cat /var/log/fluxbox/fluxbox.log

查看系统 openbox 日志

cat /var/log/openbox/openbox.log

查看系统 pekwm 日志

cat /var/log/pekwm/pekwm.log

查看系统 awesome 日志

cat /var/log/awesome/awesome.log

查看系统 i3 日志

cat /var/log/i3/i3.log

查看系统 bspwm 日志

cat /var/log/bspwm/bspwm.log

查看系统 herbstluftwm 日志

cat /var/log/herbstluftwm/herbstluftwm.log

查看系统 dwm 日志

cat /var/log/dwm/dwm.log

查看系统 xmonad 日志

cat /var/log/xmonad/xmonad.log

查看系统 qtile 日志

cat /var/log/qtile/qtile.log

查看系统 spectrwm 日志

cat /var/log/spectrwm/spectrwm.log

查看系统 monsterwm 日志

cat /var/log/monsterwm/monsterwm.log

查看 systemd 日志

journalctl -u systemd

查看 systemd-journald 日志

journalctl -u systemd-journald

查看 systemd-logind 日志

journalctl -u systemd-logind

查看 systemd-networkd 日志

journalctl -u systemd-networkd

查看 systemd-resolved 日志

journalctl -u systemd-resolved

查看 systemd-timesyncd 日志

journalctl -u systemd-timesyncd

查看 systemd-udevd 日志

journalctl -u systemd-udevd

查看 systemd-user-sessions 日志

journalctl -u systemd-user-sessions

查看 systemd-coredump 日志

journalctl -u systemd-coredump

查看 systemd-boot 日志

journalctl -u systemd-boot

查看 systemd-fsck 日志

journalctl -u systemd-fsck

查看 systemd-random-seed 日志

journalctl -u systemd-random-seed

查看 systemd-sysctl 日志

journalctl -u systemd-sysctl

查看 systemd-sysusers 日志

journalctl -u systemd-sysusers

查看 systemd-tmpfiles 日志

journalctl -u systemd-tmpfiles

查看 systemd-update-utmp 日志

journalctl -u systemd-update-utmp

查看 systemd-userdbd 日志

journalctl -u systemd-userdbd

查看 systemd-veritysetup 日志

journalctl -u systemd-veritysetup

查看 systemd-volatile-root 日志

journalctl -u systemd-volatile-root

查看 systemd-ac-power 日志

journalctl -u systemd-ac-power

查看 systemd-backlight 日志

journalctl -u systemd-backlight

查看 systemd-binfmt 日志

journalctl -u systemd-binfmt

查看 systemd-coredump 日志

journalctl -u systemd-coredump

查看 systemd-firstboot 日志

journalctl -u systemd-firstboot

查看 systemd-hibernate 日志

journalctl -u systemd-hibernate

查看 systemd-hostnamed 日志

journalctl -u systemd-hostnamed

查看 systemd-hwdb 日志

journalctl -u systemd-hwdb

查看 systemd-importd 日志

journalctl -u systemd-importd

查看 systemd-initctl 日志

journalctl -u systemd-initctl

查看 systemd-journal-gatewayd 日志

journalctl -u systemd-journal-gatewayd

查看 systemd-localed 日志

journalctl -u systemd-localed

查看 systemd-machined 日志

journalctl -u systemd-machined

查看 systemd-modules-load 日志

journalctl -u systemd-modules-load

查看 systemd-portabled 日志

journalctl -u systemd-portabled

查看 systemd-quotacheck 日志

journalctl -u systemd-quotacheck

查看 systemd-remount-fs 日志

journalctl -u systemd-remount-fs

查看 systemd-rfkill 日志

journalctl -u systemd-rfkill

查看 systemd-sleep 日志

journalctl -u systemd-sleep

查看 systemd-socket-proxyd 日志

journalctl -u systemd-socket-proxyd

查看 systemd-storagetm 日志

journalctl -u systemd-storagetm

查看 systemd-suspend 日志

journalctl -u systemd-suspend

查看 systemd-sysctl 日志

journalctl -u systemd-sysctl

查看 systemd-timedated 日志

journal

想知道

在HarmonyOS Next中,处理低内存设备资源加载主要通过以下技术:

  1. 按需加载:仅当组件可见或即将使用时才加载对应资源。
  2. 资源分级管理:根据设备内存配置自动匹配不同分辨率的资源包。
  3. 内存预警与释放:系统监测到内存不足时,自动释放非关键资源并通知应用清理缓存。
  4. 虚拟内存优化:采用高效的内存压缩与交换机制减少物理内存占用。

在HarmonyOS Next中,处理低内存设备上的大图资源加载,推荐使用ImageSourceImageDecoder进行区域解码和渐进式加载。

核心方案是使用ImageSource.createIncrementalSource()创建增量数据源,配合ImageDecoder分块解码。关键步骤:

  1. 创建增量数据源:
let incrementalSource = image.createIncrementalSource();
  1. 分块读取并解码:
// 读取图块数据
let dataChunk = ... // 获取部分数据
incrementalSource.updateData(dataChunk, false);

// 创建解码器并设置采样率
let decoder = await ImageDecoder.create(incrementalSource);
decoder.desiredSize = { width: targetWidth, height: targetHeight }; // 设置目标尺寸

// 解码指定区域
let decodeRegion = { 
  x: regionX, 
  y: regionY, 
  width: regionWidth, 
  height: regionHeight 
};
let pixelMap = await decoder.decodeRegion(decodeRegion);
  1. 显示解码后的图块:
// 将pixelMap设置给Image组件
this.imageComponent.pixelMap = pixelMap;

对于地图图块这类超大图像,建议:

  • 实现分片加载策略,按可视区域动态加载
  • 根据设备内存情况调整解码尺寸和采样率
  • 使用LruCache缓存最近使用的图块
  • 监听内存压力事件,及时释放不可见图块资源

这种流式加载方式可以有效避免OOM,同时保持流畅的用户体验。

回到顶部