H5和安卓交互时,H5渲染滞后的坑

Unity WebRTC云渲染:移动端浏览器实时3D交互实战 WebRTC是一种面向实时音视频与数据传输的底层通信协议,其基于UDP的低延迟、双向通道特性,使其成为云渲染场景中替代传统HTTP流或WebGL本地渲染的关键技术。在工业数字孪生、AR远程辅助、云游戏原型等需要高保真3D交互的领域,Unity Render Streaming通过服务端实时渲染+WebRTC流式推流,突破移动端算力与兼容性瓶颈。它依托浏览器原生解码能力,无需安装App,支持触摸/陀螺仪等多模态输入回传,并通过DataChannel实现毫秒级状态同步。本文聚焦真实产线落地中的编码适配、信令健壮 阅读详情

一、H5页面和安卓如何交互的

1.为什么会有h5和安卓的交互?

在手机app中,有时候需要在app中嵌入h5网页,能增加app的跨平台性,也就是相同的h5也可以嵌在ios平台。减少跨平台的开发成本。

同时,也能增强响应速度,减少内存消耗等优点。

2.如何交互?

主要在app中镶嵌webview的方式。webview可以看做一个内置浏览器,在webview中通过链接进入页面。

h5调移动端:在app中定义一个全局方法A,h5去调用。

移动端调h5:相同的,在h5 中定义一个全局方法B,然后app中调用。

一次完整的交互:由于h5调用app中的方法A没有返回值,需要app再主动调用一次h5的方法B,去拿app的返回值。

整个流程可以简化为:H5 --A()–> app --B()–> H5

app端代码:

前提:在安卓中引入webview。下面的代码在基于webview的框架下写的

通过移动端的@JavascriptInterface 在webview中定义一个全局的方法(window.xxx())。然后h5中直接通过window.xxx()去调用移动端方法。(代码1)

	// 入参分别为service(需要被调用的服务名),data(调用服务的参数),funcIndex(回调方法的唯一标识)
    @JavascriptInterface
    fun callMobile(service:String, data: String, funcIndex: String) {
        // 睡2秒,模拟被调用时的运行时间
        Thread.sleep(2000)
        println("调用")
        handler.post {
            // 调用js中定义的方法
            webview.loadUrl("javascript:callbackFun('$data', '$uuid')");
        }
    }
H5代码:

定一个公共方法:(代码2)

/**
 * 用于缓存回调方法,使用map形式,每个回调方法都有对应的key
 */
const funcIndexMap = new Map();

/**
 * 封装的用于调用安卓方法的通用性方法
 * @param service 需要被调用的服务名
 * @param data 调用服务的参数
 * @param func 回调方法,用于前端处理安卓的返回值
 */
export const callLocal = (
  service: string,
  data: string,
  func: any
) => {
  // 添加一个loading框,用来演示页面渲染的结果
  Toast.loading({
    duration: 0,
    message: "加载中...",
    forbidClick: true,
  });
  // 添加回调函数到map
  const uuidNo: string = uuid();
  funcIndexMap.set(uuidNo, func);
  // 调用安卓
  if (/(Android)/i.test(navigator.userAgent)) {
    //判断是安卓用户的时候执行调用安卓中定义的方法
    window.android.callMobile("xxxx",data, uuidNo);
  }
};

在页面调用(我使用的时vue3+ts的框架),给页面一个按钮定义一个事件,让该事件去调用上面的公共方法,该事件的代码为:(代码3)

defaultOffice = 'qqqq'
const back = () => {
    defaultOffice = "start";
    // 调用方法
    callLocal("",defaultOffice + "123",
      (res:any) => {
          defaultOffice = res;
      },
      true
    );
  };
  
  
// h5中定义的回调函数,用于被安卓调用
window.callbackFun = (data: string, uuidNo: string, inBack: boolean) => {
  const getFunc = funcIndexMap.get(uuidNo);
  getFunc(data);
  funcIndexMap.delete(uuidNo);
};

二、问题描述

1.场景

像上面那样运行的结果,将会是下面这样:

点击按钮后,页面没有变化

在这里插入图片描述

2秒后,才出现loading,而且对应的值被修改
在这里插入图片描述
并没有出现想象中的,点击按钮就出现loading,然后2秒后值被修改。

因为按照代码逻辑,我们想要的结果是:

  1. OFFICE号初始化是qqqq

  2. 执行back() 函数,进入back后,首先会修改defaultOffice为start。此时页面上的OFFICE号显示为start

  3. 然后调用calLocal方法,进入此方法后,首先会加在loading

  4. 然后调用安卓的方法window.android.callMobile,等待安卓方法执行完后(2秒后执行完),会执行回调函数,将值改为over。

简化对比实际和预计的结果就是:

  • 实际:点击 —> 2s后 —> loading —> 改为over

  • 预计:点击 --> loading --> 2s后 —> 改为over

三、问题分析

先一句话概括:就是运行安卓的这个方法(window.android.callMobile)会阻塞js的执行

通过上述场景,我们发现,页面重新渲染是在安卓中的方法执行完成后。执行安卓方法的关键代码虽然就一句window.android.callMobile("xxxx",data, uuidNo);,但是在它之前的代码被执行后并没有将页面渲染。即使修改了defaultOffice的值,页面也没有变化。只有在等到最后安卓的方法被执行后,页面才会被重新渲染。

这一现象启发了我,让我重温了js的执行原理。最终找到了真相。

最终原因是js是单线程的,它会等上一句代码解析执行完成后,才会执行下一行。具体原理可参考:https://www.jianshu.com/p/1368d375aa66。

我们这里就是因为js执行到window.android.callMobile时,在里面有2s的时间阻塞,导致整个callLocal方法不能执行完成,从而导致整个back方法不能执行完成,所以对于页面来说你这个back方法还没执行完,我的defaultOffice参数被改成什么了我也不知道,所以页面才没被重新渲染。

为什么我们平时在方法中修改变量不会有这个问题?

因为我们在平时的js方法中修改外部变量时,方法很快被执行完毕,我们感受不到,但如果我们像下面这样写,在defaultOffice被修改后,执行一个稍微耗时的for循环,就会发现页面上office的值会在点击事件后隔一段时间才被修改为start

const back = () => {
  defaultOffice = "start";
  for (let i = 1; i<10000; i++) {
    console.log("i:", i)
  }
};

四、问题解决

一句话:使用setTiimeout()

问题根本找到了,我们需要解决的就是不要让window.android.callMobile方法的执行阻塞住我们的js线程,我们需要让它异步执行。


而根据setTimeout(fun,time)的原理:setTimeout和setInterval会将指定的代码移出本轮事件循环,得到下一轮事件循环,再检查是否到了指定时间,如果到了就执行对应代码,如果不到,就继续等待。所以它们都会等到本轮事件循环的所有同步任务都执行完,才开始执行。对于setTimeout来说,我们哪怕设置他的时间为0,它也会等到下一轮执行。

所以我们需要将callLocal方法修改为:

export const callLocal = (
  service: string,
  data: string,
  func: any
) => {
  Toast.loading({
    duration: 0,
    message: "加载中...",
    forbidClick: true,
  });
  const uuidNo: string = uuid();
  funcIndexMap.set(uuidNo, func);
  if (/(Android)/i.test(navigator.userAgent)) {
    //修改的地方
    setTimeout(() => {
        window.android.callMobile("xxxx",data, uuidNo);
    },0)
  }
};

修改之后即可完美实现。

五、优化同步异步调用

异步方法定义:

经过修改后我们使用callLocal()方法就可以像使用普通的,但是在方法的定义中去添加回调函数显得比较乱,阅读性不强,我们稍稍进行一些优化,使用Promise将它的回调函数转移到then中。

/**
 * 异步调用安卓方法
 * @param service
 * @param data
 * @param inBack
 */
const asyncCallLocal = (
  service: string,
  data: string,
  inBack: boolean
) => {
  return new Promise((resolve) => {
    console.log("进入promise");
    callLocal(
      service,
      data,
      (data: any) => {
        resolve(data);
      },
      inBack
    );
  });
};

页面使用:

const back = () => {
    defaultOffice = "start";
    // 使用
    asyncCallLocal("",defaultOffice + "123",true).then((res:any) => {
      defaultOffice = res
    })
    defaultOffice = "end"
  };

由于这是异步方法,如果像上面那样调用,defaultOffice显示的结果将会是:

start —> end —> start123

同步方法定义:

如果想要让他同步进行修改想让defaultOffice最后被改为end,则需要定义一个同步的方法,让上面的asyncCallLocal()被同步执行即可。

定义如下:

/**
 * 同步调用安卓
 * @param service
 * @param data
 * @param inBack
 */
const syncCallLocal = async (
  service: string,
  data: string,
  inBack: boolean
) => {
  let result: any = null;
  await asyncCallLocal(service, data, inBack).then((res) => {
    result = res;
  });
  return result;
};

使用:

const back = async () => {
    defaultOffice = "start";
    
    personalData.defaultOffice = await syncCallLocal(
        "",
        defaultOffice + "123",
        true
    );

    defaultOffice = await syncCallLocal(
        "",
        defaultOffice + "aaa",
        true
    );
  };

执行结果:start —> start123 —> start123aaa

Vant移动端日历组件van-calendar白屏问题解决:手把手教你H5页面适配技巧 本文深入剖析了Vant移动端日历组件van-calendar在H5页面中首次打开白屏的根本原因,涉及浏览器渲染惰性、CSS硬件加速及Vue更新周期。提供了从强制触发浏览器重排、优化CSS渲染到调整组件生命周期的多维实战解决方案,并分享了可复用的高阶函数封装技巧,帮助开发者彻底解决此移动端适配难题。 阅读详情

相关推荐

【005安卓开发方案调研】之Flutter+Dart技术开发安卓

Flutter+Dart在国内安卓生态已达到商业应用成熟度,可复刻90%以上的主流App功能。其开发效率优势和跨端一致性对中小企业尤其具有吸引力,但需在性能优化和混合开发上投入额外精力。随着2025年Flutter 4.0对折叠屏设备和车载系统的深度适配,其生态价值将进一步提升。

ThinkPet 1384

Unity可玩广告H5导出实战:Luna Playable避坑与性能优化指南

WebGL技术将高性能的图形渲染与交互能力带入了浏览器环境,其核心原理在于将C/C++等代码编译为WebAssembly字节码,并利用现代GPU硬件加速进行渲染。这项技术的核心价值在于实现了无需插件、跨平台的富媒体应用部署,极大地拓展了Web应用的可能性。在游戏与互动营销领域,WebGL是实现H5游戏和可玩广告的关键技术栈,尤其适用于对性能和包体有严苛要求的场景。本文聚焦于使用Luna Playable插件将Unity项目优化导出为H5可玩广告的完整流程,深入剖析了在包体压缩、性能调优和平台兼容性方面遇到的

weixin_33938733的博客 424

uni-app H5项目实战:pdf.js本地部署与Base64流预览的完整避坑指南

本文详细介绍了在uni-app H5项目中实现pdf.js本地部署与Base64流预览的完整避坑指南。从pdf.js版本选择、static目录路径处理到Base64流转换和移动端优化,全面解析开发过程中可能遇到的疑难问题,帮助开发者高效完成PDF预览功能的集成与部署。

weixin_33670786的博客 421

Android和H5之间的交互

  1.设置允许执⾏JS脚本:webSettings.setJavaScriptEnabled(true); 2.添加通信接⼜ webView.addJavascriptInterface(Interface,"InterfaceName") 3. JS调AndroidInterfaceName.MethodName 4. Android调JS无返回值的   webView.loadUrl...

xlwang9090的博客 642

H5动感歌词实现:KRC解析与Uni-App音频同步技术详解

在Web前端开发中,音频处理与动态渲染是构建富媒体应用的核心技术。其原理涉及音频时间轴的精确控制、二进制数据解析以及高性能动画渲染。这些技术为在线音乐、语音交互等场景提供了关键支持,能显著提升用户体验。本文聚焦于KRC歌词格式的解密与解析,通过异或算法处理加密数据,并详细探讨了在Uni-App H5环境下,如何利用CSS3动画与音频事件同步,实现流畅的动感歌词效果,解决了移动端性能优化与跨端通信等工程难题。

weixin_30621711的博客 368

一套代码跨三端运行APP技术栈方案(ios/安卓/鸿蒙)

跨端开发框架选择分析:uni-app凭借Vue3+TypeScript技术栈、多端兼容性(Android/iOS/HarmonyOS)和丰富生态,成为覆盖国内市场的首选方案,尤其适合中小型项目快速启动。开发工具建议以HBuilderX为主,配合DevEco Studio完成鸿蒙端构建。案例验证表明uni-app可支撑电商、政务等复杂场景,未来可通过uni-appx原生渲染方案实现性能升级,并平滑过渡到鸿蒙原生应用。该方案兼具开发效率和演进灵活性,支持业务从Web到原生的渐进式优化。

m0_53592266的博客 2275

实现:H5与原生APP(Android或Ios)相互交互。

第1步:在utils目录下新建bridge.js文件。 // bridge.js: 用于实现H5跟Ios交互的工具。 export const setupWebViewJavascriptBridge = (callback) => { if ((window).WebViewJavascriptBridge) { return callback((window).WebViewJavascriptBridge) } if ((window).WVJBCallbacks) {

qq_38969618的博客 1972

京东快递H5项目接入vite实战

本文介绍了跨平台技术的演进,跨平台技术选型的要素以及各个方向的优劣势,以及结合Flutter平台能力结合后台实现低代码面向业务的具体落地实践。Flutter结合如今大红大紫的低代码(Low-Code),实现研发到业务、平台到具体场景的轻、快、易;实现业务应用的快速交付、降低业务应用的开发成本。期望读者对新技术有所了解,乐于学习分享,勇于落地实践。创新是经济的原动力。

2301_76741586的博客 489

2024年安卓最全android与H5交互方法简介,熬夜整理Android面试笔试题

本人从事Android开发已经有十余年,算是一名资深的移动开发架构师了吧。根据我的观察发现,对于很多初中级Android工程师而言,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。所以在此将我十年载,从萌新小白一步步成长为Android移动开发架构师的学习笔记,从Android四大组件到手写实现一个架构设计,我都有一一的对应笔记为你讲解。当然我也为你们整理好了百度、阿里、腾讯、字节跳动等等互联网超级大厂的历年面试真题集锦。

2401_84123077的博客 674

告别插件依赖:在Vue3项目中手把手集成pdf.js-dist实现H5端PDF预览(附完整代码)

本文详细介绍了在Vue3项目中集成pdf.js-dist实现H5端PDF预览的完整方案。通过对比传统插件,pdf.js-dist在移动端兼容性、渲染速度和内存占用方面表现更优。文章提供了从零开始的配置指南、文件流处理技巧、移动端优化策略以及企业级功能扩展,帮助开发者彻底摆脱插件依赖,打造高性能PDF预览体验。

weixin_29011993的博客 420

安卓原生开发为何是初创企业的生存基础设施

安卓原生开发是移动应用开发的基础技术路径,指基于Android SDK、直接调用系统API构建高性能、高可控性客户端的能力。其核心原理在于绕过Web容器或跨端中间层,实现对硬件传感器、后台服务、离线存储及厂商推送等底层能力的稳定访问。相比H5、小程序或跨平台方案,原生开发在弱网适配、消息送达率、启动性能和隐私合规等方面具备不可替代的技术价值。典型应用场景包括社区团购实时订单同步、智能硬件蓝牙联动、车载Android Auto集成、金融类App安全保活等强交互、低延迟、高可靠性需求领域。对于资源有限的初创企业

weixin_30776545的博客 452

高性能渲染——详解Html Canvas的优势与性能

分层Canvas的核心理念是,动态页面中的每种元素(层)对于渲染频率的需求是不同的。本文通过介绍Canvas的原理、Canvas的重要性、Canvas在计算与渲染上的作用、Canvas渲染性能优势和Canvas的应用这五个部分,全面而系统地阐述了HTML Canvas在高性能渲染方面的相关知识和技巧。因此,判断对象是否位于 Canvas 范围内需要进行额外的计算(例如,需要通过对游戏角色的全局模型矩阵求逆来得出对象的世界坐标,这是一项相对耗时的操作),同时也会增加代码的复杂性。因此,关键是是否需要这样做。

葡萄城技术团队博客 1621

Unity原生WebView集成实战:从原理到避坑的完整指南

WebView作为移动开发中的核心组件,本质上是将系统浏览器内核嵌入到原生应用中的技术方案。其原理是通过调用Android的android.webkit.WebView或iOS的WKWebView,在应用内创建一个独立的渲染环境,从而实现对HTML5、CSS3和JavaScript的完整支持。这项技术的核心价值在于实现了原生应用与Web技术的深度融合,既能利用Web生态的丰富内容与动态更新能力,又能保持原生应用流畅、沉浸的用户体验。在应用场景上,它广泛应用于活动公告展示、第三方支付集成、H5小游戏加载以及构

weixin_34226182的博客 467

vue-cli4+vue2兼容安卓7(h5嵌入app),一步步排查发现问题并且解决(vue白屏)

vue-cli4+vue2兼容安卓7(h5嵌入app),一步步排查发现问题并且解决(vue白屏)

weixin_39838846的博客 2397

HttpClient跳过HTTPS证书验证的3种实战方法(含完整代码示例)

本文详细介绍了HttpClient跳过HTTPS证书验证的3种实战方法,包括自定义TrustManager、SSLContext配置和HttpClientBuilder高级定制,并提供完整代码示例。这些方法适用于开发和测试环境,帮助开发者快速解决自签名证书或未认证证书导致的HTTPS请求失败问题,但需注意生产环境的安全风险。

weixin_29213655的博客 530

ROS Noetic + Realsense ROS 2.3.2 在鲁班猫4上的完整工作空间搭建与相机启动调试

本文详细介绍了在鲁班猫4(RK3588S)开发板上搭建ROS Noetic与Realsense ROS 2.3.2开发环境的完整流程,包括Realsense SDK安装、工作空间配置、D435i深度相机驱动调试等关键步骤,为机器人视觉系统开发提供实用指南。

weixin_33217202的博客 238

Android TV H5应用开发实战:WebView架构、遥控器交互与性能优化

在智能电视和OTT设备普及的背景下,Web前端技术栈凭借其开发效率与跨平台优势,正成为大屏应用开发的重要选择。其核心原理在于通过WebView组件将H5页面嵌入原生Android应用中,形成“原生壳+Web内容”的混合架构,从而在保留Web动态更新能力的同时,获得应用商店分发和系统集成的能力。这种架构的技术价值在于,它允许Web开发者利用熟悉的HTML5、CSS和JavaScript技术快速进入电视端开发,无需深入学习全新的原生开发语言。在应用场景上,尤其适合内容展示型、UI更新频繁的应用,如视频点播、信息

weixin_30383279的博客 412

姿态传感器/陀螺仪之BMI270应用原理图设计

BMI270是一款由博世(Bosch)推出的高性能、超低功耗惯性测量单元(IMU),专为可穿戴设备、智能设备及物联网应用设计。

corlin6688的博客 2864

【Android -- 性能优化】腾讯 TBS X5 内核:从系统 WebView 迁移到高性能混合渲染引擎

本文详细解析了腾讯TBS X5内核在Android性能优化中的关键作用,对比系统WebView在加载速度、视频播放等方面的显著优势。通过实战案例和代码示例,展示了如何迁移到X5内核并优化性能,包括内存管理、混合渲染及防劫持方案,帮助开发者提升H5页面体验。

weixin_30435261的博客 488

华为OD机试双机位C卷 - 高矮个子排队 (C++/Py/Java/Js/Go/C)

华为OD机试双机位C卷 高矮个子排队,提供C语言、Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解。华为OD机试 - 高矮个子排队。

qq_45776114的博客 2160

【1】Java 部分笔试题解析

解析A.abstract关键字应该放在class关键字之前。C.抽象方法不能有方法体。D缺少了class关键字。

博客 3943

Flutter学习(1,android开发文档下载

为了解决原生开发面临的问题,混生开发应运而生。混生开发最大的特点就是跨平台(跨Android、IOS),也就是说,Android和IOS可以共同使用多段代码,并且没有编译、性能上的差异。 主要分为三类: H5+原生(Cordova、Lonic) 在原生开发的基础上,使用 《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》 【docs.qq.com/doc/DSkNLaERkbnFoS0ZF】 完整内容开源分享 例如WebView的控件来展示H5网页。这样就能动态更新

m0_64383184的博客 186

Python 爬虫实战:爬取哔哩哔哩知识区,抓取高赞课程信息

哔哩哔哩(Bilibili)是一个广受欢迎的综合性视频社区,其中的知识区汇聚了大量优质的教育、科普、技术等课程内容。本文将指导读者如何使用 Python 爬虫技术从哔哩哔哩知识区抓取高赞课程信息,并进行数据分析。本文深入探究了利用 Python 爬虫技术从哔哩哔哩知识区抓取高赞课程信息的全流程。从前期的环境搭建、模拟登录,到核心的课程数据抓取、存储,再到后续的数据分析与可视化,都详细展开讲解并提供代码支持。通过此方法所获取的数据,能够助力创作者优化内容、用户发现优质课程、平台洞察用户需求。

u014481728的博客 1137

Flutter学习(1)初识Flutter,腾讯团队实力打造flutter入门教程

跳槽季整理面试题已经成了我多年的习惯!在这里我和身边一些朋友特意整理了一份快速进阶为Android高级工程师的系统且全面的学习资料。涵盖了Android初级——Android高级架构师进阶必备的一些学习技能。附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题(含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。本文在开源项目:【

m0_60607971的博客 1006

SAP BTP Trial 生命周期全解析:90 天试用、30 天活跃规则、Kyma 有效期与向 Free Tier 的顺滑迁移

摘要: SAP BTP免费试用账号(trial)提供90天有效期,需每30天登录一次保持活跃状态。Kyma运行时有效期仅14天,需特别注意重建。到期后数据不可恢复,建议将关键配置脚本化并保存。若需长期使用,可迁移至无时间限制的免费层(free tier)。文章详细拆解了试用生命周期规则,包括续期、删除机制,并针对CAP开发、集成套件和Kyma等场景提供实操建议,帮助用户规避常见误区,高效利用试用资源。(150字)

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 368

【Bug已解决】[Bug]: ValueError: No user query found in messages QWEN 3.5 27B VLLM 0.16.0 NIGHTLY 解决方案

用 vLLM 0.16.0 nightly 给发聊天请求时,服务端在处理消息时抛ValueError,请求失败。

博客 412
上一篇: iview实现表格动态添加输入框校验
下一篇: 发布订阅模式
落叶惊雷
博客等级 码龄12年 15粉丝 58原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值