DCloud_Android_ST
DCloud_Android_ST
  • 发布:2019-11-01 12:13
  • 更新:2020-05-27 09:39
  • 阅读:9045

Android webview隐藏后跳转新页面input输入卡顿与白屏渲染慢的问题说明及修复方案

分类:uni-app

关于此问题的说明:

Android System WebView 内核的bug:当webview页面中存在持续渲染(如跑马灯效果。banner轮播等)。页面被隐藏后会导致JS阻塞影响页面渲染效率。从66.0.3359.126版本到最新都存在此问题。
注意:

  • 此问题必须是页面隐藏hide后,并且当前页面包含持续渲染(如跑马灯效果。banner轮播等)时才会触发此问题。如果你的页面不会隐藏、没有持续渲染逻辑可忽略此问题。
  • 一般新窗体进入盖住老窗体,不会调用webview的hide方法,不会引发此问题。此问题常见于tabbar的切换,不同tab的webview页面只有一个是显示的,其他是hide的。或者开发者手动调用了plus.webview对象的hide方法。

解决方案:

方案1: 我们推荐开发者在页面被hide后,主动停用持续操作ui的js或css。
在隐藏的页面持续操作视图本身也不合理,影响性能。
在uni-app中,基础组件swiper和扩展uni ui的跑马灯,组件内部会判断,如果当前页面已经不再前台显示,会停止轮播。所以正常使用这些组件也不会遇到问题。
如果开发者引用了未做判断的三方组件,或者自己编写了持续操作视图的代码,则应该注意编写判断代码,在页面hide时,停止这些js或css。然后在恢复显示时,重新启用它们。

在uniapp中实现方案1的代码

//组件内监听webview隐藏停止动画(即将新增组件所在页面的生命周期,可以监听页面隐藏来停止动画)  
mounted() {  
  // #ifdef APP-PLUS  
  const pages = getCurrentPages();  
  let currentWebview = pages[pages.length - 1].$getAppWebview();  
  currentWebview.addEventListener('hide', () => {  
    // webview隐藏,停止动画  
  })  
  currentWebview.addEventListener('show', () => {  
    // webview显示,开启动画  
  })  
  // #endif  
},
//页面内监听页面隐藏停止动画  
onShow() {  
  // 页面显示,开启动画  
},  
onHide() {  
  // 页面隐藏,停止动画  
}

方案2: 当页面被隐藏时主动调用webview的pause方法,暂停这个webview里的所有js和css动画的运行
首先需要升级HBuilderX 2.3.8或更高版本。(如发现版本没更新请等待更新后再操作)
5+提供了新的API ,WebviewObject对象添加pause、resume方法。

  • void pause() 暂停Webview对象,停止js执行、DOM渲染
  • void resume() 恢复Webview对象,恢复js执行、DOM渲染
  • boolean isPause() 是否暂停,暂停则返回ture,否则返回false

uniapp用户:

nvue页面无此问题。忽略即可。
vue页面:
在页面存在持续渲染(如跑马灯效果。banner轮播等)的情况下。可在页面周期onShow、onHide分别调用webview的resume、pause方法即可

onShow() {  
    const w = this.$mp.page.$getAppWebview();  
    if(w.isPause()){  
        w.resume();  
    }  
},  
onHide() {  
    const w = this.$mp.page.$getAppWebview();  
    w.pause();  
},

5+用户:

可以通过WebviewObject对象控制管理方式规避问题。当调用WebviewObject的show、hide方法时主动调用相关页面的pause、resume方法。

//创建页面 此页面包含持续渲染(如跑马灯效果。banner轮播等)的逻辑存在。  
var a = plus.webview.open('list.html','list');  
//当a页面要隐藏时可调用如下代码  
var a = plus.webview.getWebviewById('list');  
a.hide('none');  
a.pause();  

//当a页面显示时调用如下代码  
var a = plus.webview.getWebviewById('list');  
if(a.isPause()) {  
   a.resume();  
}
5 关注 分享
DCloud_uniCloud_WYQ Nocker 飘过大山 skysowe 4***@qq.com

要回复文章请先登录注册

Nocker

Nocker

希望尽快 发布新版本
2019-11-04 11:41
DCloud_Android_ST

DCloud_Android_ST (作者)

回复 优乐美 :
2.3.8及以上版本
2019-11-04 11:09
优乐美

优乐美

Uncaught TypeError: ass.resume is not a function
Uncaught TypeError: ass.pause is not a function
5+ 找不到这两个方法
2019-11-02 16:48