[关闭]
@pockry 2017-10-29T15:21:02.000000Z 字数 6224 阅读 1913

小米直达服务介绍与开发实战

未分类

作者:董红光


今天想和大家分享的是小米直达服务平台,主要会围绕项目的背景和理念、平台的技术架构、以及一个简单的开发示例来展开。

1 背景理念

直达服务想解决什么样的问题呢?我们可以先看看 PC 端用户是如何使用服务的。在 PC 端,除了游戏和部分专业软件以外,绝大多数情况,用户使用的都是浏览器,打开搜索引擎,搜索关键字,点击 URL 进入服务网站,使用过程中可能还会通过链接进入到另一个服务网站,但整个过程是非常顺畅的,不需要下载软件,服务之间的跳转连接也是无缝的。

但移动端却不是这样的,移动端服务的承载主要有两种形式,网页和应用,分别来看:

网页在移动端和 PC 端的地位有着天壤之别,原因主要有两个:

第一,移动端会用到大量的硬件能力,比如拍照、扫码、定位、指纹、蓝牙、传感器,等等,但是大部分能力都没有相应的 API 能够让网页使用,这就意味着用网页承载服务很可能并不完整;

第二,移动端的芯片能力比 PC 端还是要弱一些,但是界面的复杂性和要求却很高,再加上前端技术的灵活性和历史包袱,导致移动端网页非常容易变得卡顿、慢、内存占用高,使用体验非常糟糕,想做到流畅需要花费很高的代价,而且依然很难达到原生应用的效果。

而另一种承载形式——应用——同样有两个很严重的问题:

第一,想使用服务,必须先下载安装应用,通常有几十兆左右,可能用户在外面需要流量下载,可能网络速度比较慢需要等待 10 分钟以上,而等到下载安装完了,可能已经太晚用不上或者想不起来再用了,这中间有一个非常严重的断档等待期;

第二,应用的孤岛现象严重,即便已经安装了这些应用,你会发现,大部分应用之间依然无法无缝衔接,取而代之的是,一个应用中打开的是另一个服务的网页,而网页的体验经常比较糟糕,而且可能承载不了服务,这就意味着用户的操作流程可能会断掉,需要手动切到另一个应用继续接下来的操作,这对于用户来说是难以忍受的。

而孤岛现象的另一个重要体现在于很难做应用内搜索,大部分情况用户还是只能到各个应用中分别搜索,而不是一个地方搜索全部内容。

理想的移动端服务形态,应该能够像 PC 端浏览器一样的流畅体验,具体来说,就是能够结合移动端网页和应用的优点,既不需要下载安装,功能服务又完整,还能达到原生般的流畅,服务间还能无缝打通和互相索引。我们觉得这样的服务形态应该是未来很重要的一种形式,理应对此进行探索,所以才有了直达服务这个项目。

直达服务平台就是我们对上述理想的移动端服务形态的一种探索和尝试,初步达到了我们的预期,接下来在讲平台架构时会详细说明我们在技术上是怎么做到的。

这里再多说一点入口层面的事情,通常情况下,移动端服务的发现主要有三类,应用商店、搜索、场景化。直达服务充分发挥了直达服务自身的优势和 MIUI 的优势,深挖了搜索和场景化入口,举两个例子:第一个例子,在全局搜索或浏览器搜索中,可以输入一个特定内容,比如一本漫画的名字,那么无需安装漫画应用,即可直接打开诸如快看漫画这样的直达服务,以等同于原生应用的体验直接阅读这本漫画;第二个例子,在上面提到的传送门场景之下,发现一个特定内容,比如一个电影的名字,那么同样无需安装电影应用,即可直接打开诸如豆瓣电影这样的直达服务浏览电影评价。

这里先给大家发一段视频,让大家对直达服务有一个直观的印象:

2 平台架构

直达服务平台上的各个服务采用前端技术栈开发,但是并不跑在浏览器或 WebView 中,它舍弃了浏览器内核渲染,转而采用 Android 的原生渲染机制,也就是说,实际上是使用前端技术栈开发了一个原生应用,无论是渲染效率,还是系统能力的 API 丰富程度,都远远超出传统网页。

同时,直达服务又不像原生应用先把完整应用下载下来才能运行,反而和网页类似,只下载当前需要的部分,由于这部分通常来说非常小,网络条件良好的情况下,一般不超过 1 秒即可打开服务。从开发效率角度看,直达服务和前端开发是比较接近的,采用了前端主流的模版 + 数据绑定的 MVVM 模式,非常容易理解和上手。

平台的技术架构是这样的:

首先,它有一个运行时环境,即runtime,能够支撑一个直达服务的应用正常运行,这个runtime的架构示意图如下:

runtime架构

这里简单说明一下:

  1. 左侧黄色部分,我们提供了一套原生渲染引擎,支持将前端代码渲染成原生应用,同时我们也支持直接渲染在浏览器内核中,在此基础之上,我们封装了一套组件标签库,除了HTML中比较常用的以外,还有很多高阶语义的标签,比如列表、tab、轮播图等等,所有标签在原生渲染和浏览器内核渲染条件下都能使用

  2. 中间黄色部分,我们提供了一套桥接能力,将系统的接口能力暴露到前端,在此基础之上,我们暴露了大量的系统能力,比如文件存储、二维码扫描、设备信息等等,另外还集成了很多常见服务,比如推送、帐号、支付等等,在右侧紫色部分表示

  3. 上方蓝色部分,我们提供了一套JavaScript形式的开发框架,封装了底层的这些功能,并且提供了很多应用开发需要的功能,比如页面管理、页面路由、MVVM支持,等等

有了运行时环境还不够,由于是平台,需要支持多个应用运行、分发、隔离等等,我们基于runtime,打造了一整套完整的平台,平台的架构示意图如下:

platform架构

这里简单说明一下:

  1. 横线上方是客户端,左侧是入口app,比如全局搜索、应用商店等等,右侧是直达服务应用,中间是最核心的平台apk,里面大体有四个部分,runtime就是上面提到的运行时环境,除此以外还有应用的沙盒管理、分发管理、元数据管理等等功能

  2. 横线下方是服务器,包括上文提到的诸如推送、帐号、支付等常见的应用服务,以及开发者后台服务,另外就是平台自身的各种服务,比如分发、统计、应用仓库等服务

3 开发实战

接下来我想通过一个最简单的应用——todos,来为大家展示直达服务的应用开发过程。

整个过程从环境准备到项目成型,包含7个部分:

  1. 环境准备

  2. 运行HelloWorld

  3. 增加首页

  4. 添加标题

  5. 支持撰写内容

  6. 展示内容列表

  7. 调试工具

3.1 环境准备

在开发之前,需要保证以下环境安装并配置好:

当开发者按照框架规范开发出应用之后,需要编译构建,得到一个后缀名为rpk的zip格式文件,该文件即可在手机的直达服务平台中运行。

大致过程如下:

  1. 新建工程

  2. 开发项目,更新项目代码

  3. 编译构建工程

  4. PC端启动Server,提供HTTP请求服务

  5. 手机端平台请求应用文件,下载完成后,运行应用

3.2 运行HelloWorld

  1. 开发者选定文件夹作为代码工程的目录,在目录的命令行中执行mix init todos,新建todos项目,生成项目的基本代码。工程主要包含三个目录:

    • src:项目源文件夹

    • node_modules:项目的依赖类库

    • sign:签名模块,确保构建产出的内容安全

  2. 进入项目目录下,通过npm install安装依赖,如:webpack,babel等。

  3. 通过npm run build编译项目,会在dist目录下生成rpk文件,该文件是一个zip格式的文件,用于在手机上运行。

  4. 通过npm run server让项目目录提供HTTP服务,供手机发送HTTP请求获取该文件。

  5. 手机端打开调试apk,界面如下图所示:

    debug应用

  6. 在app内扫描PC输出的二维码,点"在线更新"即可看到最初的模版页面效果:

    最初效果

  7. 开发者可以修改src/Demo/index.mix页面中的模板文本内容,然后在PC端编译项目,手机端更新项目,就会得到修改后的页面效果。

  8. 为了避免每次代码改动都要手动更新,开发者也可以使用npm run watch替代npm run build,完成实时监听代码文件的更新并自动编译。

本项目用于开发todos应用,最终效果如下:

最终效果

功能很简单,也没有细调样式,只是作为示例展示。

3.3 增加首页

我们先新增一个页面。

增加页面:新建src/Home文件夹,内部增加index.mix文件,内容如下:

code-01

可以看到,页面由template/style/script这3个根节点组件构成:

1) template:模板用于放置DOM树,只能有一个根节点,在里面可以使用各种组件标签,并配置数据进行绑定或者使用指令,如for, if, show

2) style:即CSS样式表,用于配置页面样式,为了方便CSS预处理,我们也支持less预编译能力,在style节点上增加属性lang="less"的声明即可

3) script:提供对页面的动态交互能力,如数据更新、事件响应,生命周期等

例如,绑定页面的onInit,onReady事件,在页面数据初始化、节点渲染完成后输出日志:

code-02

更新项目配置:修改src/manifest.json,增加Home页面的路由,项目起始页修改为Home,最终router配置如下:

code-03

这里需要说明几点:

1) manifest.json为项目配置文件,其中的router属性用于设置应用内的页面路由

2) router.pages对象表示应用的所有页面路由,当前我们有Demo、Home两个页面

3) router.entry属性表示应用启动时默认加载的页面,我们让应用默认启动加载Home页面

重新加载manifest.json中的路由配置后,手机端即可看到效果。

3.4 添加标题

接下来将为页面增加一个todos标题,文本居中靠上展示。

模板中增加text组件,并使用div组件的header类进行包围:

code-04

按照预览效果,我们将页面放在div.page-home节点中,页面分为上下两块,.header用于放置标题与input内容。

样式中更新text组件的样式:

code-05

这里需要说明几点:

1) 使用less预编译能力,需要声明lang="less"

2) 页面布局使用Flex布局模型,开发者可以灵活使用flex-direction等常用的flex属性

3) 通过组件标签的class属性声明样式,除了flex属性,开发这还可以使用常用的line-height, color等CSS属性

更新手机端即可看到效果:

标题预览

3.5 支持撰写内容

接下来将为页面增加input组件,完成一条记录的添加操作。

增加input组件:

code-06

这里需要说明几点:

1) 使用input[type=text]组件,表示用户输入的内容,然后在该节点上监听onchange事件

2) 使用input[type=button]组件,表示用户点击添加的按钮,然后在该节点上监听onclick事件

  1. 更新样式:

code-07

这里需要说明几点:

1) .header下新增.new-item的class声明

2) 使用CSS属性border设置div组件的边框

3) 使用width/height属性设置节点的宽高

增加业务逻辑:

脚本导出的对象会被框架作为ViewModel,主要用途有:

1) 提供生命周期的响应

2) 提供props/data属性,用于完成数据的存取能力,底层进行数据驱动能力的实现

3) 提供事件绑定,开发者可以将节点的事件绑定到VM对象的方法上

我们在VM上添加input更新内容的事件绑定updateValue(),和按钮响应增加记录的事件绑定addItem()

code-08

这里需要说明几点:

1) ViewModel的data中定义newItemName属性用于记录用户输入的内容

2) ViewModel的data中定义listData属性用于记录用户的输入列表

3) ViewModel中绑定input[type=text]的事件到方法updateValue(),用于更新内容

4) ViewModel中绑定input[type=button]的事件到方法addItem(),用于将记录增加到列表中

使用prompt接口进行提示:

如果用户没有输入内容,那么可以使用toast提示用户,只有输入内容才可以新增。

这时需要在脚本中引入prompt接口,并调用其showToast()方法,由于使用接口,我们需要在manifest.json中声明对prompt接口的使用:

code-09

更新手机端即可看到效果:

输入预览

3.6 展示内容列表

接下来要将用户输入的内容列表显示出来。

模板中增加list组件:

code-10

这里需要说明几点:

1) 增加list组件,用于展示DOM列表,匹配的子组件内容使用list-item组件

2) 组件list-item,每一条单独的记录会使用它来渲染

3) list-item上通过type属性标识不同种类的DOM布局,会在原生端进行视图复用

4) 组件block是一个逻辑节点,不会被渲染,该组件上的数据绑定会根据指令进行处理并渲染内部子组件

5) 指令for用于迭代listData列表,循环输出每条记录,内部提供了$item表示每条记录供子组件引用,$idx表示记录索引

6) 增加input[type=checkbox]组件,表示是否该待办事项是否已完成,绑定方法modifyItemStatus()

7) 增加text组件,展示X删除待办事项的功能,绑定click事件到方法deleteItem($idx)

为list组件增加样式:

code-11

这里增加了.main的class声明,表示列表模块的样式。

增加业务逻辑:

如上述模板中所示,我们需要增加两个事件响应:标识待办事项完成、删除待办事项。

最终代码如下:

code-12

这里需要说明几点:

1) 新增方法modifyItemStatus():点击列表中的checkbox,标识该todo已经完成或者未完成

2) 新增方法deleteItem():点击列表中每行结束时的X标识,用于删除该条记录

更新手机端即可看到最终效果:

最终效果

3.7 调试工具

这里我也顺便介绍一下直达服务提供的调试工具,与传统的浏览器JS调试一样,直达服务的JS调试也是通过浏览器的调试器(比如chrome的dev-tools)来完成的,不同的是直达服务是通过浏览器打开调试页面来完成的。

要开始调试,首先在PC端需要启动Debug Server,可以运行命令:npm run debug,此时会启动一个HTTP Server,用于提供HTML调试页面的请求,默认地址为:"http://localhost:8081/"。

浏览器打开这个地址,可以看到二维码输出,然后在手机端app中扫描二维码,完成PC端浏览器与手机端运行平台的连接,即可在浏览器查看到当前页面的渲染效果,如下图:

调试效果

开发者可以在调试窗口中看到工具提供了:Elements、Console、Sources、Network四个面板,包含我们最常用的大部分调试功能。

1) 面板Elements可以看到DOM树结构,开发者也可以查看节点样式;,如下图:

调试JS

2) 面板Console执行JS脚本,查看对象,如下图:

调试效果

3) 面板Sources用于调试JS业务逻辑,可以看到渲染当前页面的JS脚本,如下图:

调试效果

左侧列出页面JS文件,可以双击看到页面内容,进而在里面的JS注入断点,当事件发生时即可完成调试的功能:

调试JS

如上图所示,在addItem()内打断点,当手机完成点击Add按钮时会将JS线程停止到断点处,然后就可以做单步调试了。

4) 面板Network会记录页面所发起的所有HTTP请求,与传统一致,因为示例没有HTTP请求就不展示了。

4 结语

以上就是小米直达服务平台的基本介绍,目前平台处于内测期间,接下来很快会对外开放,欢迎大家关注,有任何问题,可以随时和我联系,谢谢大家。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注