HBuilderX

HBuilderX

极客开发工具
uni-app

uni-app

开发一次,多端覆盖
uniCloud

uniCloud

云开发平台
HTML5+

HTML5+

增强HTML5的功能体验
MUI

MUI

上万Star的前端框架

上海力谱云分析开发一款电商APP软件的关键原因

2018年成就了诸多如拼多多、云集、兴盛优选等电商平台黑马,却也让不少线下创业项目折戟沉沙。越来越多的企业家与创业者开始发现,想要在2019年做一个好的好项目,无论如何做都绕不过要开发一款属于自己的电商软件应用。专业提供电商软件开发的力谱云,为您提供多种移动电商解决方案。下面力谱云首先为您分析开发电商软件的三大关键原因。

中国移动用户流量源源不断,线上市场蛋糕丰厚

据全球移动应用数据分析平台App Annie统计,在过去一年中,全球App软件应用下载量突破1900亿次,其中,中国用户的App下载量竟然达到了50%的助攻力。并且,在2018年中,平均每个中国用户下载了大约五十个左右的手机应用软件,每天会有3.5小时用于手机App。这不光光是在意味着全球App的历史性突破,更是中国商业市场成熟迈进移动蓝海的时代性标志。目前,据统计力谱云的企业用户范围,不仅包含一二线城市,越来越多的三四五线城市创业家也关注到了开发并运营一款电商软件,对于未来企业发展的决定性作用。

逆消费升级现象纷涌显现,物美价廉成追捧

近期,社交分销、社区团购、拼团购物等商业红利项目如春笋般络绎不绝地显现市场,凭借着购物返利、性价比高等特点,吸引了大批中低层消费人群的瞩目,大幅带动了三四五线城市的消费力拉动。事实上,越来越多的消费者开始比起品牌,更开始关注物品是否价美物廉,因此逆消费升级现象的出现,捧红了不少电商App平台,如拼多多等。现在,创业家只需通过力谱云开发一款企业专属电商软件,就能快速部署多级分销机制、拼团营销活动,通过秒杀、满减优惠等吸引眼球的前沿营销手法,即可开启2019年创业之旅。那么,开发电商App的投入高,风险高吗?

电商软件开发技术成熟,成本降低至传统开发1成

众所周知,App开发市场早已成熟,力谱云平台通过创新的云计算模式,可以大幅降低研发门槛,进而降低在开发一款电商软件中的资本投入。在传统市场,往往需要数月周期打造,并需要高达数十万不止的成本进行投入,且伴随App成品无法交付的巨大风险。而力谱云平台所开发的电商软件平台则恰恰相反。只需传统开发的1成开发成本,即可打造一款覆盖苹果、安卓、微官网、小程序、移动网站的电商软件平台,并且拥有数十类市场前沿营销工具,在交付前企业即可见到App产品雏形,大幅避免开发风险,让创业者能所见即所得。并且在后续运营中,无需任何技术人员参与,即可简单操作,人力成本也可大大节约。因此,目前开发电商软件App平台成为了众多创业者的选择。

总结一番,移动App市场成熟,用户量级别大,通过App平台可以轻而易举地达成,在线下营销环节中无法做到的营销活动,可以大幅提升企业服务品质,同时也降低运营成本。通过小本投资并开发一款属于个人的电商软件开发项目,企业即可获得更多的盈利渠道,何乐而不为呢?2019年,从小本投资并开发一款属于自己的电商软件平台开始吧!

继续阅读 »

2018年成就了诸多如拼多多、云集、兴盛优选等电商平台黑马,却也让不少线下创业项目折戟沉沙。越来越多的企业家与创业者开始发现,想要在2019年做一个好的好项目,无论如何做都绕不过要开发一款属于自己的电商软件应用。专业提供电商软件开发的力谱云,为您提供多种移动电商解决方案。下面力谱云首先为您分析开发电商软件的三大关键原因。

中国移动用户流量源源不断,线上市场蛋糕丰厚

据全球移动应用数据分析平台App Annie统计,在过去一年中,全球App软件应用下载量突破1900亿次,其中,中国用户的App下载量竟然达到了50%的助攻力。并且,在2018年中,平均每个中国用户下载了大约五十个左右的手机应用软件,每天会有3.5小时用于手机App。这不光光是在意味着全球App的历史性突破,更是中国商业市场成熟迈进移动蓝海的时代性标志。目前,据统计力谱云的企业用户范围,不仅包含一二线城市,越来越多的三四五线城市创业家也关注到了开发并运营一款电商软件,对于未来企业发展的决定性作用。

逆消费升级现象纷涌显现,物美价廉成追捧

近期,社交分销、社区团购、拼团购物等商业红利项目如春笋般络绎不绝地显现市场,凭借着购物返利、性价比高等特点,吸引了大批中低层消费人群的瞩目,大幅带动了三四五线城市的消费力拉动。事实上,越来越多的消费者开始比起品牌,更开始关注物品是否价美物廉,因此逆消费升级现象的出现,捧红了不少电商App平台,如拼多多等。现在,创业家只需通过力谱云开发一款企业专属电商软件,就能快速部署多级分销机制、拼团营销活动,通过秒杀、满减优惠等吸引眼球的前沿营销手法,即可开启2019年创业之旅。那么,开发电商App的投入高,风险高吗?

电商软件开发技术成熟,成本降低至传统开发1成

众所周知,App开发市场早已成熟,力谱云平台通过创新的云计算模式,可以大幅降低研发门槛,进而降低在开发一款电商软件中的资本投入。在传统市场,往往需要数月周期打造,并需要高达数十万不止的成本进行投入,且伴随App成品无法交付的巨大风险。而力谱云平台所开发的电商软件平台则恰恰相反。只需传统开发的1成开发成本,即可打造一款覆盖苹果、安卓、微官网、小程序、移动网站的电商软件平台,并且拥有数十类市场前沿营销工具,在交付前企业即可见到App产品雏形,大幅避免开发风险,让创业者能所见即所得。并且在后续运营中,无需任何技术人员参与,即可简单操作,人力成本也可大大节约。因此,目前开发电商软件App平台成为了众多创业者的选择。

总结一番,移动App市场成熟,用户量级别大,通过App平台可以轻而易举地达成,在线下营销环节中无法做到的营销活动,可以大幅提升企业服务品质,同时也降低运营成本。通过小本投资并开发一款属于个人的电商软件开发项目,企业即可获得更多的盈利渠道,何乐而不为呢?2019年,从小本投资并开发一款属于自己的电商软件平台开始吧!

收起阅读 »

uni-app ,H5实现lazyload

Lazyload

背景:

uni-app image组件的lazyload 不支持H5端。 这个对于有图片的长列表来说,体验很差。特别是有更多数据加载时,由于浏览器同一域名并发请求有限制,会阻塞后面的请求。因此作者使用vue-lazyload暂时解决下浏览器端的图片懒加载问题。

步骤:

安装vue-lazyload组件 。

  1. 地址:https://www.npmjs.com/package/vue-lazyload
  2. gihub : https://github.com/hilongjw/vue-lazyload
  3. 使用npm安装 ,`npm -i vue-lazyload -S

引入组件

在main.js中引入,代码如下

import VueLazyload from 'vue-lazyload'  
Vue.use(VueLazyload)

用法

图片方式

<block v-for="(item,index) in list" :key="index">  
<!-- #ifdef APP-PLUS -->  
<image  :lazy-load="true" :src="item.img"></image>  
<!-- #endif -->  
<!-- #ifdef H5 -->  
<img  v-lazy="item.img">  
<!-- #endif -->  
</block>  

背景图方式

<block v-for="(item,index) in list" :key="index">  
<!-- #ifdef APP-PLUS -->  
<image  :lazy-load="true" :src="item.img"></image>  
<!-- #endif -->  
<!-- #ifdef H5 -->  
<view  v-lazy:background-image="{loading:'/static/loading.png',error:'/static/error.png',src:item.img}"></view>  
<!-- #endif -->  
</block>  

自定义样式

img[lazy=loading] {  
    /*加载中*/  
}  
img[lazy=error] {  
    /*加载失败*/  
}  
img[lazy=loaded] {  
    /*加载完成*/  
}

更多用法请参考文档

继续阅读 »

背景:

uni-app image组件的lazyload 不支持H5端。 这个对于有图片的长列表来说,体验很差。特别是有更多数据加载时,由于浏览器同一域名并发请求有限制,会阻塞后面的请求。因此作者使用vue-lazyload暂时解决下浏览器端的图片懒加载问题。

步骤:

安装vue-lazyload组件 。

  1. 地址:https://www.npmjs.com/package/vue-lazyload
  2. gihub : https://github.com/hilongjw/vue-lazyload
  3. 使用npm安装 ,`npm -i vue-lazyload -S

引入组件

在main.js中引入,代码如下

import VueLazyload from 'vue-lazyload'  
Vue.use(VueLazyload)

用法

图片方式

<block v-for="(item,index) in list" :key="index">  
<!-- #ifdef APP-PLUS -->  
<image  :lazy-load="true" :src="item.img"></image>  
<!-- #endif -->  
<!-- #ifdef H5 -->  
<img  v-lazy="item.img">  
<!-- #endif -->  
</block>  

背景图方式

<block v-for="(item,index) in list" :key="index">  
<!-- #ifdef APP-PLUS -->  
<image  :lazy-load="true" :src="item.img"></image>  
<!-- #endif -->  
<!-- #ifdef H5 -->  
<view  v-lazy:background-image="{loading:'/static/loading.png',error:'/static/error.png',src:item.img}"></view>  
<!-- #endif -->  
</block>  

自定义样式

img[lazy=loading] {  
    /*加载中*/  
}  
img[lazy=error] {  
    /*加载失败*/  
}  
img[lazy=loaded] {  
    /*加载完成*/  
}

更多用法请参考文档

收起阅读 »

Android Studio 控制台输出console.log

log

踩坑分享经验: 包名不要改,要用默认的io.dcloud.HBuilder。这样js输出和报错都能正常显示。
Manifest.xml和gradle文件,这两个地方把包名改回来

踩坑分享经验: 包名不要改,要用默认的io.dcloud.HBuilder。这样js输出和报错都能正常显示。
Manifest.xml和gradle文件,这两个地方把包名改回来

uniapp h5如何动态设置页面title

h5

使用传统的JS即可设置

    document.title = _self.AgentSystemSet.WebSiteName;

http://ask.dcloud.net.cn/question/68050?item_id=82508&rf=false

继续阅读 »

使用传统的JS即可设置

    document.title = _self.AgentSystemSet.WebSiteName;

http://ask.dcloud.net.cn/question/68050?item_id=82508&rf=false

收起阅读 »

Mac系统,HBuilderX无法启动、点击无反应、点击后弹跳退出的解决方案

HBuilderX Mac

此帖子为mac解决方案,windows请参考:http://ask.dcloud.net.cn/article/35583


Mac上 HBuilderX起不来,主要有两种:

  • 新下载的起不来,请参考第一章
  • 以前可以启动,后来起不来,请略过第一章,直接看第二章

1. 重点:新下载的HBuilderX无法启动

近来,部分小伙伴反馈,刚下载的HBuilderX,安装后,点击启动,在程序呜弹跳了几下,闪退了。

解决方案:重启电脑

2. 删除.lock文件

打开操作系统终端,输入如下命令:

rm -f $HOME/Library/Application\ Support/HBuilder\ X/.lock

如删除.lock文件还无法解决启动问题,请尝试删除配置文件目录。

3. 配置文件损坏,导致无法启动

有可能是配置文件损坏了,直接删除配置文件即可。

配置文件目录:$HOME/Library/Application\ Support/HBuilder\ X

**请注意:** mac上,如果路径包含空格,需要\进行转义

如果您愿意提供损坏的配置文件给我们分析问题,这样有助于帮助其他人 email: ide@dcloud.io

$ 请在终端执行以下命令,把配置文件拷贝到桌面,并发送给我们  
$ cp -rf $HOME/Library/Application\ Support/HBuilder\ X   $HOME/Desktop/HX

删除损坏的配置文件,在命令行输入。注意:删除前,请先备份。

$ 如HBuilderX内,有重要文件,删除前,先备份  
$ rm -rf $HOME/Library/Application\ Support/HBuilder\ X

如果还是不行,重启电脑试试

4. 如果出现所有插件安装失败,请参考http://ask.dcloud.net.cn/article/36085

5. 联系方式

Mac专用交流群:148229211
Email: ide@dcloud.io

继续阅读 »

此帖子为mac解决方案,windows请参考:http://ask.dcloud.net.cn/article/35583


Mac上 HBuilderX起不来,主要有两种:

  • 新下载的起不来,请参考第一章
  • 以前可以启动,后来起不来,请略过第一章,直接看第二章

1. 重点:新下载的HBuilderX无法启动

近来,部分小伙伴反馈,刚下载的HBuilderX,安装后,点击启动,在程序呜弹跳了几下,闪退了。

解决方案:重启电脑

2. 删除.lock文件

打开操作系统终端,输入如下命令:

rm -f $HOME/Library/Application\ Support/HBuilder\ X/.lock

如删除.lock文件还无法解决启动问题,请尝试删除配置文件目录。

3. 配置文件损坏,导致无法启动

有可能是配置文件损坏了,直接删除配置文件即可。

配置文件目录:$HOME/Library/Application\ Support/HBuilder\ X

**请注意:** mac上,如果路径包含空格,需要\进行转义

如果您愿意提供损坏的配置文件给我们分析问题,这样有助于帮助其他人 email: ide@dcloud.io

$ 请在终端执行以下命令,把配置文件拷贝到桌面,并发送给我们  
$ cp -rf $HOME/Library/Application\ Support/HBuilder\ X   $HOME/Desktop/HX

删除损坏的配置文件,在命令行输入。注意:删除前,请先备份。

$ 如HBuilderX内,有重要文件,删除前,先备份  
$ rm -rf $HOME/Library/Application\ Support/HBuilder\ X

如果还是不行,重启电脑试试

4. 如果出现所有插件安装失败,请参考http://ask.dcloud.net.cn/article/36085

5. 联系方式

Mac专用交流群:148229211
Email: ide@dcloud.io

收起阅读 »

我做了一个数字华容道,谁要挑战一下?我最快记录1分38秒

我做了一个数字华容道,谁要挑战一下?我最快记录1分38秒,链接:https://www.pgyer.com/shuzihrd

我做了一个数字华容道,谁要挑战一下?我最快记录1分38秒,链接:https://www.pgyer.com/shuzihrd

关于HBuilderX后期会不会支持二进制查看功能呢?

如图不知道大家有没有这个需求。HBuilderX是一款很好的果餐软件,希望可以支持二进制查看。

如图不知道大家有没有这个需求。HBuilderX是一款很好的果餐软件,希望可以支持二进制查看。

关于dcloud.io和uniapp.dcloud.io被谷歌误报安全问题的注意

误报

【更新:】此问题已申诉完毕,google已经不再提醒安全问题。

================以下为过期内容=================

目前chrome浏览器和部分Safari浏览器访问dcloud.io和uniapp.dcloud.io会提示安全告警。

原因

事情起因是百度JQuery公共库被Chrome/火狐/Safari报毒,dcloud.io域名下个别页面引用了百度JQuery公共库资源,故dcloud.io及子站访问被浏览器拦截。

我们已修改文件引用地址,并向谷歌申诉解除误报。

建议方案

推荐开发者:

社区、插件市场、开发者中心等网站不受影响。

继续阅读 »

【更新:】此问题已申诉完毕,google已经不再提醒安全问题。

================以下为过期内容=================

目前chrome浏览器和部分Safari浏览器访问dcloud.io和uniapp.dcloud.io会提示安全告警。

原因

事情起因是百度JQuery公共库被Chrome/火狐/Safari报毒,dcloud.io域名下个别页面引用了百度JQuery公共库资源,故dcloud.io及子站访问被浏览器拦截。

我们已修改文件引用地址,并向谷歌申诉解除误报。

建议方案

推荐开发者:

社区、插件市场、开发者中心等网站不受影响。

收起阅读 »

UniApp Android 通知栏音乐控制 播放/上一首/下一首/ 小插件

通知栏 音乐播放 uniapp插件

通过Android 通知栏,控制音乐的播放/暂停/ 上一首/下一首 功能,我们很常见的音乐类APP都会有的音乐播放控件,通过 uniapp 插件扩展也可以实现这个功能,在开发视听类APP时,为混合APP增加多一种特色。

图片

如何使用,最好在程序主页面操作,避免其他子页面关掉后,而失效。

1. 引用插件

var music= require('../../common/html5app-music-not.js');

2.插件的相关方法

方法名称 说明
show() show 方法包含4个参数 ,调用它会显示通知栏播放控件出来,1. 歌曲标题,2.歌曲封面图片,3.上一首按键是否可用, 4.下一首按钮是否可用。
setplayicon() music.setplayicon(false); 默认false , false 显示暂停图标, true 显示播放图标
setlastOrnext() music.setlastOrnext({last:"false",next:"true"}); 设置上一首、下一首按键是否可用
close() music.close(); 关掉通知栏

3. 安卓扫一扫,下载体验

图片

扫一扫下载 安卓 DEMO 示例 体验, 或者电脑下载

原文链接 :http://www.html5-app.com/show/118

继续阅读 »

通过Android 通知栏,控制音乐的播放/暂停/ 上一首/下一首 功能,我们很常见的音乐类APP都会有的音乐播放控件,通过 uniapp 插件扩展也可以实现这个功能,在开发视听类APP时,为混合APP增加多一种特色。

图片

如何使用,最好在程序主页面操作,避免其他子页面关掉后,而失效。

1. 引用插件

var music= require('../../common/html5app-music-not.js');

2.插件的相关方法

方法名称 说明
show() show 方法包含4个参数 ,调用它会显示通知栏播放控件出来,1. 歌曲标题,2.歌曲封面图片,3.上一首按键是否可用, 4.下一首按钮是否可用。
setplayicon() music.setplayicon(false); 默认false , false 显示暂停图标, true 显示播放图标
setlastOrnext() music.setlastOrnext({last:"false",next:"true"}); 设置上一首、下一首按键是否可用
close() music.close(); 关掉通知栏

3. 安卓扫一扫,下载体验

图片

扫一扫下载 安卓 DEMO 示例 体验, 或者电脑下载

原文链接 :http://www.html5-app.com/show/118

收起阅读 »

小程序输入框被键盘遮挡的话,input加上cursor-spacing属性就ok了

uniapp 输入框 微信小程序

小程序输入框被键盘遮挡的话,input加上cursor-spacing属性就ok了

小程序输入框被键盘遮挡的话,input加上cursor-spacing属性就ok了

uni-app HBuilderX 工程与 vue-cli 工程相互转换

vue_cli

uni-app 工程创建

https://uniapp.dcloud.io/quickstart

HBuilderX 工程转换为 vue-cli 工程

vue-cli 版更新频率较高,当需要使用一些新特性时可以转换为 vue-cli 工程

步骤

  1. 使用 vue-cli 4 新建空工程
  2. 将 HBuilderX 工程内的文件(除 unpackage、node_modules 目录)拷贝至 vue-cli 工程内 src 目录
  3. 在 vue-cli 工程内重新安装 npm 依赖(如果之前使用了 npm 依赖的话)

vue-cli 工程转换为 HBuilderX 工程

不需要转换,把cli工程拖入HBuilderX中,可直接编辑、运行、发布。

继续阅读 »

uni-app 工程创建

https://uniapp.dcloud.io/quickstart

HBuilderX 工程转换为 vue-cli 工程

vue-cli 版更新频率较高,当需要使用一些新特性时可以转换为 vue-cli 工程

步骤

  1. 使用 vue-cli 4 新建空工程
  2. 将 HBuilderX 工程内的文件(除 unpackage、node_modules 目录)拷贝至 vue-cli 工程内 src 目录
  3. 在 vue-cli 工程内重新安装 npm 依赖(如果之前使用了 npm 依赖的话)

vue-cli 工程转换为 HBuilderX 工程

不需要转换,把cli工程拖入HBuilderX中,可直接编辑、运行、发布。

收起阅读 »

浅谈移动端 View 的显示过程

view

*作者:个推安卓开发工程师 一七***

随着科技的发展,各种移动端早已成为人们日常生活中不可或缺的部分,人们使用移动端产品工作、社交、娱乐……移动端界面的流畅性已经成为影响用户体验的重要因素之一。那么你是否思考过移动端所展现的流畅画面是如何实现的呢?

本文通过对移动端View显示过程的简略分析,帮助开发者了解View渲染的逻辑,更好地优化自己的APP。

上图展示的是一个完整的页面渲染过程。通过上图,我们可以初步了解每一帧页面从代码布局的编写到展示给使用者,其背后的逻辑是如何一步一步执行的。

屏幕如何呈像

像素点

在电子屏幕中显示的图片,其实都是由一个个“小点”所组成的,这些“小点”被称为“像素点”。每一个像素点都有自己的颜色,每一张完整的图片都是由它们相连拼接形成的。

每个像素点一般都有 3 个子像素:红、绿、蓝,根据这三种原色,我们能够调制出各种各样的颜色。

大电视机

与现在的平板电视不同的是,以前的黑白电视机或者大背投彩电,总是带着大大的“后背”。“大后背”电视其实就是阴极射线管电视机,俗称显像管电视。其成像原理是电子枪发射出的电子束(阴极射线)通过聚焦系统和偏转系统,射向屏幕上涂有荧光层的指定位置。被电子束轰击的每个位置,荧光层都会产生一个小亮点,最终小亮点们将会组成一幅幅影像,显示在电视屏幕上。

这也是以前大电视机的屏幕都呈圆弧形的原因。因为越接近圆形,边长到中心的距离越相近,呈像越均匀。那为什么当磁铁贴近电视机时,会让电视机的成像出现问题呢?那是因为磁铁会干扰电子束的正常轨迹,并且在贴近屏幕的时候,也可能使得屏幕的荧光层磁化,出现一个个不正常的光斑。

LCD 和 OLED

随着科技的不断进步,电视、手机、电脑的体积越来越薄,射线管显像方式也逐渐被淘汰。目前在手机市场上占据主流地位的是 LCD 和 OLED 两种屏幕。

LCD 全称为 Liquid Crystal Display ,即液晶显示器。OLED 全称为 Organic Light-Emitting Diode ,即有机发光二极管。这两者之间存在显著的差别:

1. 两者成像原理不同
LCD 是靠白色的背光穿透彩色薄膜显色的,而 OLED 则是靠每个像素点自行发光。

2. 在耗电量方面
LCD的耗电量较高,即使只显示一个亮点,LCD 的背光源也需要一直发光,而且容易出现漏光现象。而OLED的每个像素都能独立工作,而且 可以自行发光,因此采用OLED的设备可以制作得更薄,甚至可以弯曲。

3.在制作方面
LCD使用的是无机材料, OLED 则需要使用有机材料,因此 OLED的制作费用更高,并且使用寿命不如 LCD 。

图形显示核心 GPU

与CPU相对比,GPU的计算单元更多,更擅长大规模并发计算,例如密码破解、图像处理等。CPU 则是遵循冯诺依曼架构存储程序顺序执行,在大规模并行计算能力上,受到的限制更大,因此更擅长逻辑控制。

应用程序编程接口 API (OpenGL)

在没有统一的 API 之前,开发者需要在各式各样的图形硬件上编写各种自定义接口和驱动程序,工作量极大。

1990 年 SGI(硅谷图形公司)成为了工作站 3D 图形领域的领导者,并将其 API 转变为一项开放标准,即 OpenGL。后来,SGI还促成了 OpenGL 架构审查委员会(OpenGL ARB)的创建。

垂直同步 Vertical Synchronization

当我们在使用手机 APP 的过程中,发现页面出现卡顿现象,那么极有可能是页面没有在 16ms 内更新导致的。实际上,人眼与大脑之间的协作无法感知超过 60fps 的画面更新。60fps 相当于是每秒 60 帧,那么每个页面需要在 1000/60 = 16ms 内更新为其他页面,才不会让我们感受到页面的卡顿。

而在没有 VSync 的情况下可能会出现以下情况:

如上图所示,在没有 VSync 的情况下,会出现需要显示第二帧时,其尚未处理完成的情况,因此Display 中显示的仍是第一帧。这会造成该帧显示时长超过16ms,从而导致页面卡顿的现象。

为了使 CPU、GPU 生成帧的速度与 Display 保持一致,Android 系统每 16ms 就会发出一次 VSYNC 信号,触发 UI 渲染更新。

从上图中我们可以看出,每隔 16ms ,安卓会发出一个 VSync 信号,收到信号后 CPU 开始处理下一帧的的内容,GPU 在 CPU 处理结束之后,将会进行光栅化,此时屏幕上显示的是上一帧已经处理完成的页面。如此反复,就可以在页面中展示一幅幅的指定画面。而确保画面流畅的前提是CPU 和 GPU 处理一帧所花费的时间不能超过 16 ms,否则就会出现以下情况:

当CPU 和 GPU 处理一帧的时间超过了16 ms时,在第一个 Display 中,由于 GPU 处理 B 画面的时间过长,导致系统发出 VSync 信号时, Display不能及时地显示出 B 画面,而重复显示A页面,造成卡顿。

此外,在第二个 Display 中,由于 A Buffer 还在被 Display 所使用,不能在收到 VSync 信号后开始处理下一帧的页面,导致该时间段内 CPU 的闲置。为了避免这种时间的浪费,三缓存机制由此出现:

如上图所示,在三缓存机制中,当 A 缓存被 Display 使用、B 缓存被 GPU 处理时,系统会发出 Vsync 信号,并加入新的缓存 C ,用来缓存下一帧的内容。这种方式虽然不能完全避免 A页面的重复显示,但是能够让后面页面的显示更加平滑。

View 的绘制流程

View 的绘制是从 ViewRootImpl 的 performTraversals() 方法开始的,其整体流程大致分为三步,如下图所示:

measure

控件测量过程从 performMeasure() 方法开始。在该方法中childWidthMeasureSpec 和 childHeightMeasureSpec,分别是用来确定宽度和高度的。

MeasureSpec 是一个 int 值,它存储着两个信息:低 30 位是 View 的 specSize,高 2 位是 View 的 specMode。

specMode 有三种类型:

1.UNSPECIFIED

父视图对子视图没有任何限制,可以将视图按照开发者的意愿设置成任意的大小,在一般开发过程中不会用到。

2.EXACTLY

父视图为子视图指定一个确切的尺寸,该尺寸由 specSize 的值来决定。

3.AT_MOST

父视图为子视图指定一个最大的尺寸,该尺寸的最大值是 specSize。

观察 View 的 measure() 方法,可以发现该方法是被 final 修饰的,因此 View 的子类只能够通过重载 onMeasure() 方法来完成自己的测量逻辑。

在 onMeasure() 方法中:

调用 getDefaultSize() 方法来获取视图的大小:

该方法中的第二个参数 measureSpec 是从 measure() 方法中传递过来的:通过 getMode() 和 getSize() 解析获取其中对应的值,再根据 specMode 给最终的 size 赋值。

不过以上只是一个简单控件的一次 measure 过程,在真正测量的过程中,由于一个页面往往包含多个子 View ,所以需要循环遍历测量,在 ViewGroup 中有一个 measureChildren() 方法,就是用来测量子视图的:

measure 整体流程的方法调用链如下:

layout

在performTraversals() 方法的测量过程结束后,进入 layout 布局过程:

performLayout(lp,desiredWindowWidth,desiredWindowHeight);

该过程的主要作用即根据子视图的大小以及布局参数,将相应的 View 放到合适的位置上。

host.layout(0,0,host.getMeasuredWidth(),host.getMeasuredHeight());

如上,layout() 方法接收了四个参数,按照顺时针,分别是左上右下。该坐标针对的是父视图,以左上为起始点,传入了之前测量出的宽度和高度。之后,让我们进入到 layout() 方法中观察:

我们通过 setFrame() 方法给四个变量赋值,判断 View 的位置是否变化以及是否需要重新进行 layout,而且其中还调用了 onLayout() 方法。

在进入该方法后,我们可以发现里面是空的,这是因为子视图的具体位置是相对于父视图而言的,所以 View 的 onLayout 为空实现。

再进入 ViewGroup 类中查看,我们可以发现,这其实是一个抽象的方法,在这样的情况下, ViewGroup 的子类便需要重写该方法:

draw

绘制的流程主要如下图所示,该流程也是存在遍历子 View 绘制的过程:

需要注意的是,View 的 onDraw() 方法是空的,这是因为每个视图的内容都不相同,这个部分交由子类根据自身的需要来处理,才更加合理:

安卓渲染机制的整体流程

1.APP 在 UI 线程构建 OpenGL 渲染需要的命令及数据;

2.CPU 将数据上传(共享或者拷贝)给 GPU 。(PC 上一般有显存,但是 ARM 这种嵌入式设备内存一般是 GPU 、 CPU 共享内存);

3.通知 GPU 渲染。一般而言,真机不会阻塞等待 GPU 渲染结束,通知结束后就返回执行其他任务;

4.通知 SurfaceFlinger 图层合成;

5.SurfaceFlinger 开始合成图层。

总结

移动端技术发展很快,而画面显示优化是一个持续发展的实践课题,贯穿于每个开发者的日常工作中。未来,个推技术团队将继续关注移动端的性能优化,为大家分享相关的技术干货。

继续阅读 »

*作者:个推安卓开发工程师 一七***

随着科技的发展,各种移动端早已成为人们日常生活中不可或缺的部分,人们使用移动端产品工作、社交、娱乐……移动端界面的流畅性已经成为影响用户体验的重要因素之一。那么你是否思考过移动端所展现的流畅画面是如何实现的呢?

本文通过对移动端View显示过程的简略分析,帮助开发者了解View渲染的逻辑,更好地优化自己的APP。

上图展示的是一个完整的页面渲染过程。通过上图,我们可以初步了解每一帧页面从代码布局的编写到展示给使用者,其背后的逻辑是如何一步一步执行的。

屏幕如何呈像

像素点

在电子屏幕中显示的图片,其实都是由一个个“小点”所组成的,这些“小点”被称为“像素点”。每一个像素点都有自己的颜色,每一张完整的图片都是由它们相连拼接形成的。

每个像素点一般都有 3 个子像素:红、绿、蓝,根据这三种原色,我们能够调制出各种各样的颜色。

大电视机

与现在的平板电视不同的是,以前的黑白电视机或者大背投彩电,总是带着大大的“后背”。“大后背”电视其实就是阴极射线管电视机,俗称显像管电视。其成像原理是电子枪发射出的电子束(阴极射线)通过聚焦系统和偏转系统,射向屏幕上涂有荧光层的指定位置。被电子束轰击的每个位置,荧光层都会产生一个小亮点,最终小亮点们将会组成一幅幅影像,显示在电视屏幕上。

这也是以前大电视机的屏幕都呈圆弧形的原因。因为越接近圆形,边长到中心的距离越相近,呈像越均匀。那为什么当磁铁贴近电视机时,会让电视机的成像出现问题呢?那是因为磁铁会干扰电子束的正常轨迹,并且在贴近屏幕的时候,也可能使得屏幕的荧光层磁化,出现一个个不正常的光斑。

LCD 和 OLED

随着科技的不断进步,电视、手机、电脑的体积越来越薄,射线管显像方式也逐渐被淘汰。目前在手机市场上占据主流地位的是 LCD 和 OLED 两种屏幕。

LCD 全称为 Liquid Crystal Display ,即液晶显示器。OLED 全称为 Organic Light-Emitting Diode ,即有机发光二极管。这两者之间存在显著的差别:

1. 两者成像原理不同
LCD 是靠白色的背光穿透彩色薄膜显色的,而 OLED 则是靠每个像素点自行发光。

2. 在耗电量方面
LCD的耗电量较高,即使只显示一个亮点,LCD 的背光源也需要一直发光,而且容易出现漏光现象。而OLED的每个像素都能独立工作,而且 可以自行发光,因此采用OLED的设备可以制作得更薄,甚至可以弯曲。

3.在制作方面
LCD使用的是无机材料, OLED 则需要使用有机材料,因此 OLED的制作费用更高,并且使用寿命不如 LCD 。

图形显示核心 GPU

与CPU相对比,GPU的计算单元更多,更擅长大规模并发计算,例如密码破解、图像处理等。CPU 则是遵循冯诺依曼架构存储程序顺序执行,在大规模并行计算能力上,受到的限制更大,因此更擅长逻辑控制。

应用程序编程接口 API (OpenGL)

在没有统一的 API 之前,开发者需要在各式各样的图形硬件上编写各种自定义接口和驱动程序,工作量极大。

1990 年 SGI(硅谷图形公司)成为了工作站 3D 图形领域的领导者,并将其 API 转变为一项开放标准,即 OpenGL。后来,SGI还促成了 OpenGL 架构审查委员会(OpenGL ARB)的创建。

垂直同步 Vertical Synchronization

当我们在使用手机 APP 的过程中,发现页面出现卡顿现象,那么极有可能是页面没有在 16ms 内更新导致的。实际上,人眼与大脑之间的协作无法感知超过 60fps 的画面更新。60fps 相当于是每秒 60 帧,那么每个页面需要在 1000/60 = 16ms 内更新为其他页面,才不会让我们感受到页面的卡顿。

而在没有 VSync 的情况下可能会出现以下情况:

如上图所示,在没有 VSync 的情况下,会出现需要显示第二帧时,其尚未处理完成的情况,因此Display 中显示的仍是第一帧。这会造成该帧显示时长超过16ms,从而导致页面卡顿的现象。

为了使 CPU、GPU 生成帧的速度与 Display 保持一致,Android 系统每 16ms 就会发出一次 VSYNC 信号,触发 UI 渲染更新。

从上图中我们可以看出,每隔 16ms ,安卓会发出一个 VSync 信号,收到信号后 CPU 开始处理下一帧的的内容,GPU 在 CPU 处理结束之后,将会进行光栅化,此时屏幕上显示的是上一帧已经处理完成的页面。如此反复,就可以在页面中展示一幅幅的指定画面。而确保画面流畅的前提是CPU 和 GPU 处理一帧所花费的时间不能超过 16 ms,否则就会出现以下情况:

当CPU 和 GPU 处理一帧的时间超过了16 ms时,在第一个 Display 中,由于 GPU 处理 B 画面的时间过长,导致系统发出 VSync 信号时, Display不能及时地显示出 B 画面,而重复显示A页面,造成卡顿。

此外,在第二个 Display 中,由于 A Buffer 还在被 Display 所使用,不能在收到 VSync 信号后开始处理下一帧的页面,导致该时间段内 CPU 的闲置。为了避免这种时间的浪费,三缓存机制由此出现:

如上图所示,在三缓存机制中,当 A 缓存被 Display 使用、B 缓存被 GPU 处理时,系统会发出 Vsync 信号,并加入新的缓存 C ,用来缓存下一帧的内容。这种方式虽然不能完全避免 A页面的重复显示,但是能够让后面页面的显示更加平滑。

View 的绘制流程

View 的绘制是从 ViewRootImpl 的 performTraversals() 方法开始的,其整体流程大致分为三步,如下图所示:

measure

控件测量过程从 performMeasure() 方法开始。在该方法中childWidthMeasureSpec 和 childHeightMeasureSpec,分别是用来确定宽度和高度的。

MeasureSpec 是一个 int 值,它存储着两个信息:低 30 位是 View 的 specSize,高 2 位是 View 的 specMode。

specMode 有三种类型:

1.UNSPECIFIED

父视图对子视图没有任何限制,可以将视图按照开发者的意愿设置成任意的大小,在一般开发过程中不会用到。

2.EXACTLY

父视图为子视图指定一个确切的尺寸,该尺寸由 specSize 的值来决定。

3.AT_MOST

父视图为子视图指定一个最大的尺寸,该尺寸的最大值是 specSize。

观察 View 的 measure() 方法,可以发现该方法是被 final 修饰的,因此 View 的子类只能够通过重载 onMeasure() 方法来完成自己的测量逻辑。

在 onMeasure() 方法中:

调用 getDefaultSize() 方法来获取视图的大小:

该方法中的第二个参数 measureSpec 是从 measure() 方法中传递过来的:通过 getMode() 和 getSize() 解析获取其中对应的值,再根据 specMode 给最终的 size 赋值。

不过以上只是一个简单控件的一次 measure 过程,在真正测量的过程中,由于一个页面往往包含多个子 View ,所以需要循环遍历测量,在 ViewGroup 中有一个 measureChildren() 方法,就是用来测量子视图的:

measure 整体流程的方法调用链如下:

layout

在performTraversals() 方法的测量过程结束后,进入 layout 布局过程:

performLayout(lp,desiredWindowWidth,desiredWindowHeight);

该过程的主要作用即根据子视图的大小以及布局参数,将相应的 View 放到合适的位置上。

host.layout(0,0,host.getMeasuredWidth(),host.getMeasuredHeight());

如上,layout() 方法接收了四个参数,按照顺时针,分别是左上右下。该坐标针对的是父视图,以左上为起始点,传入了之前测量出的宽度和高度。之后,让我们进入到 layout() 方法中观察:

我们通过 setFrame() 方法给四个变量赋值,判断 View 的位置是否变化以及是否需要重新进行 layout,而且其中还调用了 onLayout() 方法。

在进入该方法后,我们可以发现里面是空的,这是因为子视图的具体位置是相对于父视图而言的,所以 View 的 onLayout 为空实现。

再进入 ViewGroup 类中查看,我们可以发现,这其实是一个抽象的方法,在这样的情况下, ViewGroup 的子类便需要重写该方法:

draw

绘制的流程主要如下图所示,该流程也是存在遍历子 View 绘制的过程:

需要注意的是,View 的 onDraw() 方法是空的,这是因为每个视图的内容都不相同,这个部分交由子类根据自身的需要来处理,才更加合理:

安卓渲染机制的整体流程

1.APP 在 UI 线程构建 OpenGL 渲染需要的命令及数据;

2.CPU 将数据上传(共享或者拷贝)给 GPU 。(PC 上一般有显存,但是 ARM 这种嵌入式设备内存一般是 GPU 、 CPU 共享内存);

3.通知 GPU 渲染。一般而言,真机不会阻塞等待 GPU 渲染结束,通知结束后就返回执行其他任务;

4.通知 SurfaceFlinger 图层合成;

5.SurfaceFlinger 开始合成图层。

总结

移动端技术发展很快,而画面显示优化是一个持续发展的实践课题,贯穿于每个开发者的日常工作中。未来,个推技术团队将继续关注移动端的性能优化,为大家分享相关的技术干货。

收起阅读 »