uni-app App平台iOS设备上因内存不足导致白屏、闪退的问题解决方案

发布于 1周前 作者 htzhanglong 来自 Uni-App

uni-app App平台iOS设备上因内存不足导致白屏、闪退的问题解决方案

原因

任何手机设备上,当手机内存不足时,os都会回收资源。一般是先回收后台打开的资源。如果当前应用占用的资源过高,当前应用也有可能崩溃。

尤其是在调用摄像头点击拍照时,手机内存占用会达到一个峰值,此时较容易出问题。

iOS上当内存不足时,根据uiwebview和wkwebview的不同,它自身有不同的回收策略。

  • 如果是uiwebview的app(常见于5+app),内存不足时整个app会崩溃,即闪退。
  • 如果是wkwebview的app(uni-app和wap2app在iOS上默认就是wkwebview),内存不足时,单个wkwebview会崩溃。也就是所谓的应用还在,而页面白屏。

这个问题在所有使用wkwebview的应用都会出现,比如微信的公众号网页里也存在。在微信小程序里,它做了一个自动恢复手段,可以让jscore存储数据状态,崩溃的wkwebview自动恢复。所以在遇到问题时,会白一下然后恢复渲染。

解决方案

  • uni-app因为引入了独立的jscore处理数据状态,jscore不会崩溃,所以官方采用了和微信小程序一致的策略,补充自动的白屏恢复能力。
  • uni-app中也可以使用nvue来避免这个问题,nvue页面不会出现内存不足引发的白屏崩溃。
  • 5+app、wap2app,一方面注意前端代码写法,减低内存使用。另外HBuilder2.3.4+开始支持配置WKWebview内核奔溃是重新启动应用还是重新加载页面的配置,详情参考:https://ask.dcloud.net.cn/article/36540。但整体而言,5+app和wap2app在WKWebview下问题很多,还有各种跨域限制,还是建议开发者尽快升级为uni-app。

在前端减少内存使用的注意

最重要的注意,就是图片渲染,尤其是大图片。

在页面上不要渲染多张大图,比如从摄像头或相册选择多张图,并缩放尺寸渲染在页面上,虽然肉眼看起来手机屏幕上是几张小图,但实际上是多张大图只是被缩小,这种情况非常耗费内存。一张图片3m,9张这样的大图同时渲染到屏幕上,什么手机都受不了。

一个缩略图控制在几k或十几k,才是合理的。

详情页面展现多张大图并不受影响。如果图片滚动在屏幕外,os内存不足时也会自动收回这些屏幕外图片占用的渲染资源,最吃资源的就是同屏渲染多张大图。


1 回复

针对uni-app在iOS设备上因内存不足导致的白屏、闪退问题,这通常与应用的内存管理和资源优化有关。以下是一些代码级别的解决方案,旨在帮助提升应用的内存使用效率,减少内存泄漏,并优化资源加载。

1. 优化图片资源

iOS设备对内存使用较为敏感,大图片资源是内存消耗的主要来源之一。使用uni.getImageInfo获取图片信息,并根据设备屏幕尺寸动态加载适当大小的图片。

uni.getImageInfo({
  src: 'path/to/image',
  success: function(res) {
    // 根据res.width和res.height判断图片大小,选择加载合适尺寸的图片
    let imageUrl = chooseAppropriateImageSize(res.width, res.height);
    // 设置图片到页面或组件中
  }
});

function chooseAppropriateImageSize(width, height) {
  // 逻辑:根据屏幕宽度和高度选择图片尺寸
  // 例如,如果屏幕宽度小于600,则加载小图
  if (uni.getSystemInfoSync().windowWidth < 600) {
    return 'path/to/small_image';
  } else {
    return 'path/to/large_image';
  }
}

2. 使用WeakMap/WeakSet管理对象

在JavaScript中,使用WeakMapWeakSet来存储不需要防止被垃圾回收的对象,这有助于减少内存泄漏。

let cache = new WeakMap();

function loadData(key) {
  if (cache.has(key)) {
    return cache.get(key);
  } else {
    let data = fetchDataFromServer(key); // 假设这是从服务器获取数据的函数
    cache.set(key, data);
    return data;
  }
}

3. 定时清理未使用的资源

定时清理不再使用的资源,如定时器、监听器和缓存数据,以释放内存。

let intervalId = setInterval(() => {
  // 清理逻辑:检查并清理不再需要的定时器、监听器等
  clearUnusedTimersAndListeners();
  // 清理缓存数据
  clearCacheData();
}, 60000); // 每分钟清理一次

function clearUnusedTimersAndListeners() {
  // 清理逻辑实现
}

function clearCacheData() {
  // 清理缓存数据逻辑实现
  cache = new WeakMap(); // 重新初始化缓存,或根据具体逻辑清理
}

4. 使用Instruments工具分析内存

最后,利用Xcode自带的Instruments工具对应用进行内存分析,找出内存泄漏点和内存占用高峰,针对性地进行优化。

请注意,上述代码仅为示例,具体实现需根据应用实际情况调整。内存管理是一个复杂且持续的过程,需要开发者持续关注和优化。

回到顶部