View加载

本文主要介绍了Android中View加载流程和Activity启动流程。View随Activity创建加载,经一系列方法完成布局加载与绘制。Activity启动从Context的startActivity开始,通过Instrumentation和AMS跨进程交互,完成Activity创建与启动,最终内容渲染到window上。

View加载流程:

View随着Activity的创建而加载,startActivity启动一个Activity时,在ActivityThread的 handleLaunchActivity方法中先调用Activity的attach方法初始化PhoneWindow实例, 然后会执行Activity的onCreate方法,这个时候会调用setContentView加载布局 创建出DecorView并将我们的layout加载到DecorView中,当执行到handleResumeActivity时,Activity的onResume方法被调用,然后WindowManager会将DecorView设置给ViewRootImpl。这样,DecorView就被加载到Window中了,此时界面还没有显示出来,还需要经过View的measure,layout,和 draw方法,才能完成View的工作流程。我们需要知道View的绘制是由ViewRoot来负责的,每一个DecorView都有一个与之关联的ViewRoot,这种关联关系是由WindowManager维护的,将DecorView 和 ViewRoot关联之后,ViewRootImpl的requestLayout会被调用以完成初步布局,通过scheduleTraversals方法,这个方法会执行View的measure, layout 和 draw流程。

 

AppCompatDeleagate

mDelegate = AppCompatDelegate.create

mDelegate.setContentView

AppCompatDelegateImplBase、AppCompatDelegateImplV9

@Override

public void setContentView(int resId){

    ensureSubDecor();

    ViewGroup contentParent = mSubDecor.findViewById(android.R.id.content);

    contentParent.removeAllViews();

    LayoutInflater.from(mContext).inflate(resId, contentParent);

    mOriginalWindowCallback.onContentChanged();

}

 

private ViewGroup mSubDecor;

activity.getWindow

 

mWindow是定义在Activity中的一个全局变量,mWindow赋值是在Activity方法中完成的。

Window是Android里面的一个抽象类,而PhoneWindow是Window的唯一的实现类。

PhoneWindow构造方法中很重要的一个全局变量,mDecor,这个是DecorView类的实例。那么mDecor = (DecorView) preservedWindow.getDecorView();这个方法是给DecorView赋值的。

 

Activity在调用attach时就会初始化PhoneWindow

mWindow = new PhoneWindow(this, window, activityConfigCallback);

Activity的attach是在performLaunchActivity中被调用的,也就是在ActivityThread中被调用。所以在Activity中任何时候getWindow(),都能得到PhoneWindow。

 

Activity启动流程:

我们可以从Context的 startActivity说起,其实现 是ContextImpl的 startActivity,然后内部会通过 Instrumentation 来尝试启动Activity,这是一个跨进程过程,它会调用AMS的startActivity方法,当AMS校验完activity的合法性后,会通过ApplicationThread回调到我们的进程,这也是一次跨进程过程,而ApplicationThread就是一个binder,回调逻辑是在binder线程池中完成的,所以需要通过Handler将其切换到ui线程,会收到消息------LAUNCH_ACTIVITY,它对应handleLaunchActivity,在这个方法里完成了Activity的创建和启动。接着,在activity的onResume中,activity的内容开始渲染到window上,然后开始绘制直到我们能看到。

 

 

第一个消息:H.BIND_APPLICATION

handleBindApplication()

反射得到 Instrumentation

Instrumentation会在应用程序的任何代码运行之前被实例化,可以用它来监测应用程序 和 系统的所有交互。每一个activity都会持有instrumentation的引用,但是整个进程只有一个instrumentation实例,instrumentation相当于一个大管家,管理着activity 和 application的生命周期,包括activity的创建。

Instrumentation的execStartActivity方法

通过ActivityThread,Instrumentation会来执行activity的生命周期方法以及创建activity,那么ActivityThread又是哪个类通知的呢???是AMS,也就是ActivityManagerService。

AMS通过Binder通信告诉ActivityThread,该创建一个activity了,那么ActivityThread就会调用Instrumentation来创建一个activity。

ActivityManagerNative.getDefault()返回的是ActivityManagerService的远程接口-------ActivityManagerProxy。

ActivityManagerNative.getDefault().startActivity()则利用Binder进行通信,把所有参数数据封装在Parcel对象中,然后通过binder对象的transact方法传输到AMS。

 

<think>我们正在处理支付宝小程序中web-view加载H5经常出现白屏的问题。根据引用[4]中提到的支付宝小程序的一些特点,如底层基于Lynx渲染,对CSS和组件的支持有限,以及适用于简单页面等,我们可以推断白屏问题可能与这些限制有关。同时,引用[3]中提到在支付场景中,web-view加载支付链接时的一些处理,这也提示我们可能需要注意网络请求和页面跳转的问题。 解决方案思路: 1. 检查H5页面是否符合支付宝小程序的web-view要求,包括域名白名单、HTTPS等。 2. 优化H5页面的加载性能,特别是首屏加载速度。 3. 考虑支付宝小程序对web-view组件的限制,调整H5页面的复杂度。 4. 在web-view加载过程中添加加载指示器,避免用户以为白屏。 5. 错误处理,当加载失败时给予用户反馈。 具体步骤: ### 一、基础检查 1. **域名配置**:确保H5域名已添加到支付宝小程序的域名白名单中(在支付宝开放平台配置)[^3]。 - 开发环境可临时忽略域名检查(使用`my.setIgnoreDomainCheck`),但上线前必须配置。 2. **协议要求**:H5必须使用HTTPS协议。 3. **网络状态**:检查用户网络环境,可增加网络状态监听,提示用户切换网络。 ### 二、H5页面优化 1. **减少资源体积**: - 压缩HTML、CSS、JavaScript文件。 - 使用图片懒加载或压缩图片。 - 使用CDN加速静态资源加载。 2. **减少重定向**:避免多次重定向,特别是支付宝小程序内可能对重定向次数有限制。 3. **服务端渲染(SSR)**:对于内容型页面,采用SSR可以加快首屏渲染速度[^1]。 4. **避免使用支付宝不支持的CSS特性或复杂布局**:参考引用[4],支付宝的Lynx渲染引擎对CSS支持有限,应使用简单的布局和样式。 ### 三、小程序端优化 1. **预加载机制**: ```javascript // 在需要跳转web-view的页面提前创建web-view组件,并设置src // 这样在真正打开页面时,web-view可能已经加载了一部分 // 注意:支付宝小程序不支持预加载,但可以通过提前创建web-view实例来加速 ``` 2. **显示加载状态**: ```vue <template> <web-view :src="webUrl" @load="hideLoading" @error="showError"></web-view> <loading v-if="isLoading">加载中...</loading> </template> <script> export default { data() { return { webUrl: 'https://...', isLoading: true } }, methods: { hideLoading() { this.isLoading = false }, showError() { this.isLoading = false // 显示错误提示 } } } </script> ``` 3. **超时处理**:设置超时时间,超过一定时间未加载成功则提示用户重新加载。 ```javascript setTimeout(() => { if (this.isLoading) { this.isLoading = false uni.showToast({ title: '加载超时', icon: 'error' }) } }, 10000) // 10秒超时 ``` ### 四、错误监控 1. **捕获错误事件**:通过web-view的`@error`事件捕获错误,根据错误码处理。 ```javascript handleAlipayError(e) { const errorMap = { 2: 'URL为空', 3: 'H5域名未配置', 4: '页面访问受限' } const errorMsg = errorMap[e.detail.errCode] || '未知错误' uni.showModal({ title: '加载失败', content: errorMsg }) } ``` 2. **日志上报**:将错误信息上报到服务器,便于分析。 ### 五、其他注意事项 1. **避免使用localStorage**:支付宝小程序web-view中可能不支持或有限制,使用cookie或URL参数传递信息。 2. **支付跳转问题**:参考引用[3],在支付场景中,web-view加载支付链接时,注意支付完成后的回跳链接必须是小程序页面,否则可能导致无法返回小程序。需要在支付链接中添加回跳参数(如`redirect_url`),并确保该链接已在小程序后台配置。 ### 六、复杂场景处理 如果H5页面非常复杂,且无法通过上述优化解决白屏问题,可考虑: 1. **拆解H5功能**:将部分功能改用小程序原生实现。 2. **混合渲染**:参考引用[4]中的混合渲染小程序方案,将关键部分用原生组件渲染,非关键部分用web-view。 > **总结**:支付宝小程序web-view白屏问题通常由网络、域名配置、H5页面过大或兼容性问题引起。通过优化H5页面、添加加载状态和错误处理,可以有效缓解问题。 --- §§相关问题§§ 1. 如何监控支付宝小程序中web-view加载性能? 2. 支付宝小程序web-view支持哪些HTML5特性? 3. 支付宝小程序web-view内如何实现支付并返回小程序? </think> ## 支付宝小程序 Web-View 白屏问题解决方案 支付宝小程序 Web-View 加载 H5 出现白屏问题,通常由以下原因导致,下面是针对性解决方案: ### 一、核心优化方案 #### 1. **域名配置检查(关键步骤)** ```javascript // app.js 开发环境临时忽略域名检查 App({ onLaunch() { // #ifdef MP-ALIPAY if (process.env.NODE_ENV === 'development') { my.setIgnoreDomainCheck({ ignore: true }) } // #endif } }) ``` - **必须配置**:在支付宝开放平台添加 H5 域名白名单[^3] - **协议要求**:确保使用 HTTPS 协议 - **正式环境**:移除忽略域名检查代码 #### 2. **H5 页面优化(SSR+资源压缩)** ```html <!-- H5 页面添加预加载提示 --> <div id="loading" style="position:fixed;top:0;left:0;width:100%;height:100%;background:#fff;z-index:9999"> <div>加载中...</div> </div> <script> // 页面完全加载后隐藏加载提示 window.addEventListener('load', () => { document.getElementById('loading').style.display = 'none' }) </script> ``` - **服务端渲染(SSR)**:使用 Nuxt.js 等框架实现首屏直出 - **资源压缩**: - 图片使用 WebP 格式 - 启用 Gzip/Brotli 压缩 - 合并 CSS/JS 文件 #### 3. **Web-View 加载策略优化** ```vue <template> <web-view :src="webUrl" @load="handleLoad" @error="handleError" :webview-styles="{ progress: { color: '#4fc08d' }, 'loading-view': { background: '#f8f8f8' } }"> </web-view> </template> <script> export default { data() { return { webUrl: 'https://your-domain.com/h5-page' } }, methods: { handleLoad(e) { console.log('页面加载完成', e) uni.hideLoading() }, handleError(e) { console.error('加载失败', e.detail) uni.showToast({ title: '加载失败,请重试', icon: 'none' }) // 错误重试机制 setTimeout(() => { this.webUrl = `${this.webUrl}?t=${Date.now()}` // 添加时间戳强制刷新 }, 2000) } }, onLoad() { uni.showLoading({ title: '加载中...', mask: true }) } } </script> ``` ### 二、深度优化措施 #### 1. **网络层优化** ```nginx # Nginx 配置 server { listen 443 ssl; server_name your-domain.com; # 开启 HTTP2 http2 on; # 开启 Brotli 压缩 brotli on; brotli_types text/plain text/css application/json application/javascript; # 缓存静态资源 location ~* \.(js|css|png|jpg|jpeg|gif|ico|webp)$ { expires 30d; access_log off; add_header Cache-Control "public"; } } ``` #### 2. **支付宝容器适配** ```javascript // H5 页面检测支付宝环境 if (navigator.userAgent.indexOf('AlipayClient') > -1) { // 简化页面逻辑 document.documentElement.style.setProperty('--primary-color', '#1677FF'); // 避免使用支付宝不支持的 API if (typeof IntersectionObserver === 'undefined') { console.warn('支付宝环境不支持 IntersectionObserver') } } ``` ### 三、特殊场景处理 #### 支付跳转白屏问题[^3] ```javascript // 支付链接添加回跳参数 const payUrl = `https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?redirect_url=${encodeURIComponent('alipays://platformapi/startapp?appId=yourAppId')}` // Web-View 加载支付链接 this.webUrl = payUrl ``` - **关键点**:`redirect_url` 必须包含支付宝协议头 `alipays://` - **配置**:在支付宝开放平台配置支付回跳白名单 ### 四、监控与调试 ```javascript // 添加性能监控 const timing = window.performance.timing const loadTime = timing.loadEventEnd - timing.navigationStart console.log(`页面加载耗时:${loadTime}ms`) // 发送监控数据 if (loadTime > 3000) { my.reportAnalytics('webview_slow_load', { time: loadTime }) } ``` > **最佳实践建议**: > 1. H5 页面大小控制在 1MB 以内 > 2. 首屏资源加载不超过 10 个请求 > 3. 使用支付宝官方组件替代复杂 H5 组件[^4] > 4. 复杂页面采用混合渲染方案(Lynx 渲染引擎)[^4] ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值