我们把移动端App分为四大类

  • React/Flutter App

  • Web App(纯网页)

  • Native App(纯原生App)

  • Hybrid app (混合App)

o 多View混合型:Native View与WebView交替出现的场景

o 单View混合型:在同一个View内,同时包括Native View和Web View

o Web主体型:移动应用的主体是WebView

过去收银台模块采用单View混合型,我们称之为H5收银台。H5收银台开发快,一次开发,iOS和Android两端通用。在享受开发便利的同时长期使用过程中发现:

  • H5收银台首屏加载时间长,大多数时候超过1秒以上;

  • 弹窗动画生硬,用户体验不够友好;

  • 技术栈链路过长:JDWebView容器,H5前端页面,原生页面和JDWebView统一控件交互,原生和H5页面交互,定位问题、排查问题相对耗时长;

  • 从占用手机大量内存的页面比如游戏网页跳转到收银台时,配置低的手机存在大概率性的黑屏或者白屏问题。

瓶颈是WebView,基于上述认识我们需要对业务较稳定的收银台首页去掉WebView,改成纯原生页面。改造后的架构图:

在原生化改造过程中我们面临一个选择:是继续使用Java还是选用Kotlin,收银台团队认为Kotlin是Andrioid开发的未来,谷歌的全力支持和未来丰富的语言生态让我们有理由相信Kotlin在移动端的远大且光明的前景。

接着来聊聊Kotlin和我们对Kotlin的实践,本文将从下面两部分展开:

  • 对Kotlin的理解

  • Kotlin在收银台里的具体实践

编程语言的时空观

想对Kotlin有全面、深刻的理解,还得从语言的源头入手,溯洄从之,一路探究。纵观过去100年,编程语言经历了三大阶段,分别是机器语言,汇编语言和高级语言。Kotlin隶属于高级语言,从高级语言这一阶段出发来看看编程语言的发展历程:

摘自:Most Popular Programming Languages 1965 - 2019 by youtube

上图为最受欢迎的高级语言的变化过程。高级语言从20世纪50年代到1983年为早期孕育阶段,按时间先后顺序发展出面向过程的结构化设计,面向对象的分析与设计,函数式编程范式等。随着语言的发展,原本常用的“面向对象”和“函数式”的边界变得越来越模糊。Kotlin于2011年问世,并在2017年得到谷歌官方支持,开始作为Android开发语言。

找到了Kotlin在时间轴线上的位置,Kotlin和其他语言的横向比较的位置在哪儿呢?

根据运行时是否允许隐式变量类型转换,把语言分为强类型和弱类型。Kotlin是强类型语言(隐式类型转换:不需要用户干预,编译器私下进行的类型转换行为)

根据对类型的检测时机是在编译期还是运行期,把语言分为静态语言和动态语言;Kotlin是静态语言。

根据程序的源文件被运行前是否需要提前转化为机器码,把语言分为编译型和解释型;Kotlin和Java类似,需要编译成字节码的解释型语言。

依据动态性和类型强度可以建立一个直角坐标系,如下图所示:沿着X轴正方向,静态性越来越强;沿着Y轴正方向,类型强度越来越强。

摘自网络

随着时间流逝,动态语言加入了静态能力,静态语言加入了动态能力,静态和动态正在相互靠拢,未来的编程语言属于这两者的杂交产物。Kotlin作为JVM语言,它落在第一象限,动态性比Java强,类型强度比Java弱。

小结:

于是对Kotlin的基本的认识便有了:Kotlin是现代化的编译型、强类型、静态语言。Kotlin相比于Java,更动态性,符合编程语言发展的趋势。上述所展示的Kotlin特点最终是通过语言特性得以落实。

kotlin的语言特性

语言特性分为通用特性,面向过程的特性,面向对象的特性,函数式的特性。

通用的特性,比如:

  • 变量

  • 作用域

面向过程的特性,比如:

  • 流程控制:条件语句,分支语句,循环语句

  • 基本数据类型

  • 数据容器(数组&集合)

  • 方法定义与调用

  • 访问权限

面向对象的特性,比如:

  • 类和类层次结构

  • 对象和类型

  • 封装、继承、多态、抽象

  • 接口&抽象方法

  • 混合mixin

  • 并发

  • 异常处理

  • 垃圾回收

  • 递归

函数式的特性,比如:

  • 引用透明

  • 高阶函数

  • lambda表达式

  • 模式匹配

  • Monad结构

  • 柯里化

  • 不变性&可变性

  • 闭包

Koltin和Java在语言特性上的差异

Kotlin独有的特性有:data类,sealed类,解构,中缀表达,访问范围,操作符重载,主从构造器,内部类/嵌套类,属性访问器(内置setter和getter方法),属性延迟初始化,类型继承体系。如下:

  • 增加类型继承体系

  • 增加默认参数、可变参数

  • 强化了不可变性

  • 强化了空安全

  • 强化了泛型

  • 强化了函数/lambda表达

  • 去掉了可受检异常

  • 增加了运算符重载

  • 修改了权限访问范围

  • 把最佳实践融入到语法

可以看到Kotlin和Java特性差异还是挺多的,这里举两个方面说一说:函数式和类型。

函数式

Kotlin较Java一个很大的特性差异便是对函数式的支持大大提高了。我们知道函数式基本元素有:

  • 不可变性

  • 引用透明

  • 无副作用

  • 高阶函数与lambda表达式

  • Monad结构

  • 柯里化

  • 模式匹配

  • 智能类型推断

  • 递归

  • 并发安全

函数式编程有如下等式:

程序 = 可变性程序 + 不可变性程序

可变性程序 = 对象 + 依赖关系

不可变程序 = 纯函数 + 组合 (Monad结构)

Kotlin的语言特性对此都做了支持,相比于Java在组件化和响应式上Kotlin更加简洁、直观。

类型差异

Kotlin和Java类型上的差异,有类型声明差异和类型体系差异。

类型声明差异

val a: String = "I am Kotlin"

这与函数定义时返回类型,类继承,接口实现提供了一致的书写体验

fun sum(x: Int, y: Int): Int {

Java是类型前置的写法,定义方法时返回类型写在了前面,但是继承和实现是后置的。类型后置的好处:通过类型推导实现类型省略时一致的书写体验;Kotlin做到了三种场景符号一致,书写一致(类型推导)

类型体系差异

下图是Kotlin类型体系,Kotlin把基本数据类型统一成对象类型,形成了面向对象的继承体系。

Kotlin的瑕疵

kotlin的语言特性丰富而有力,带来了与Java的特性差异。任何事物都有正、反两面,kotlin也不例外。

1)多维数组需要通过嵌套的方式创建

val bytes = Array(3) { ByteArray(4) }

对比一下Java

byte[][] bytes = new byte[3][4];

相比Kotlin的,Java清晰简便多了

2)Kotlin没法实现的接口样子

这样的Java接口

interface Itest{

在Kotlin里实现该接口,class A会因为实现了两个相同签名方法而报错

class A : Itest{

3)抛弃了受检异常(checked exception)

这是颇有争议的瑕疵,有坏处也有好处。

**坏处:**对异常不强制要求处理。有时候调用一些方法,特别涉及到硬件或者网络相关的方法,往往不一定知道它可能会抛出什么异常,或者根本不知道它会抛出异常。便会在这块地方遗漏了某些异常的处理或者没做异常处理,埋下一些潜在的问题。

**好处:**Kotlin不区分checked exception,这样能简化代码书写,符合Kotlin一贯的简洁设计理念。因此Kotlin是没有受检异常的。

Kotlin在收银台具体实践

Kotlin语言所拥有的特性为面向过程特性、面向对象特性和函数式特性的部分总和。从V9.2.2版本开始,安卓收银台模块开始全面使用Kotlin语言。为了稳定,我们采用了Java和Kotlin混合开发的模式。

01与Java的互操作

先来看看Kotlin和Java的互操作。

1)Kotlin调用Java的代码

几乎和Java调用Java代码相同,有几个不相同的点如下:

1.属性前缀

示意代码:

public final class User {

2.平台类型

kotlin调用Java代码后返回的类型在Kotlin侧叫做平台类型。平台类型既可当作可空类型也可作为非空类型。换句话说,kotlin编译时,平台类型被认为是非空类型,不需要非空判断顺利编译通过,在运行时被认为是可空类型。平台类型可能触发空指针异常。收银台空安全实践避免了这种空指针,详见后文内容。

2)Java调用Kotlin的代码

在kotlin代码上增加Kotlin注解,Java调用Kotlin便能像Java调用Java代码般

1)@JvmOverloads 默认参数重载

@JvmOverloads

引入默认参数重载的注解后,只需要一次方法定义就够满足收银台对底部支付文案的内容更新,减少了方法定义的模版代码。

2)@JvmStatic 静态

object Updater {

收银台是Java和Kotlin语言混合开发,通过这个注解,原来的Java代码调用Kotlin写的of方法就能成为我们熟知的Updater.of的样子。

3)在接口层面,Java使用Kotlin接口也做到了打通;

Java的接口 <—> Kotlin的接口 <—> Kotlin的lambda表达式

block: () -> ArrayList<Entity>

收银台kotlin侧定义的lambda表达式,被Java调用时会被识别成Java的Function系列的接口。

02收银台的空安全实践

原生收银台项目本身的代码,截止目前未出现过空指针崩溃。空指针是客观存在的,收银台是如何避免了空指针呢?借助Kotlin主要做了两个方面的工作:

1.通过Kotlin可空类型和空安全调用特性,我们把非空的判断归整到上游的接口数据层,做统一集中式的处理

示意代码如下:

public class Response extends BaseEntity implements ICheckNull {

对每个接口返回的实体类,都实现ICheckNull接口,并检查实体类里每个对象是否为null,如果为null我们额外初始化这个对象。这套逻辑借助泛型封装成了收银台的工具类,方便其他实体类复用。

2. Kotlin的平台类型可能造成的空指针异常,因此对Kotlin调用Java的代码返回的类型处理为可空类型,即做一次非空判断。除非Java代码返回能保证非空

Java侧示意代码

   public PayEntity createPayEntity(Payment payment) {

Kotlin调用Java

val payEntity: PayEntity? = Manager.getInstance().createPayEntity(payment)

除此之外利用Kotlin语言特性,我们更一步地提高了空安全。具体地说通过不可变性,属性读写分离,Elvis操作符等来实现。

1)可变与不可变性

variable = var ; value = val(final)

2)分离属性的读和写操作

Java的setter方法和getter方法内置到属性,方便分离读&写操作,有弹性。

示意代码

var age: Int = 0

3)空安全调用 & Elvis操作

Kotlin语言层面提供了便捷的空判断表达,避免了类似写Java代码通过大量if语句判空嵌套的情况。

val currentPlan: String? = defaultCard?.recommendId ?: DEFAULT_PLAN

03遇到的问题

  • 反序列化:fastjson框架反序列化Kotlin定义的的Int、Float、Double类型时,变成null而不是Java的基本数据类型值,用String类型替换原来的字段类型。

  • 平台编译失败:通过增加中间变量,变换写法而得到解决。

  • 遗漏的异常处理:NumberFormatException崩溃

NumberFormatException崩溃日志如下:

—java.lang.NumberFormatException: empty String sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1842) sun.misc.FloatingDecimal.parseFloat(FloatingDecimal.java:122) java.lang.Float.parseFloat(Float.java:451)

问题出在parseFloat(Float.java:451)方法上,看下toFloat的Kotlin实现:

@kotlin.internal.InlineOnly

Kotlin的toFloat方法内部调用了Java的parseFloat方法,Java的parseFloat源码如下:

    /**

从源码上发现parseFloat方法会抛出NullPointerException和NumberFormatException两种异常,漏做了NumberFormatException异常处理,传入了空字符串。因此调用不是自己写的方法的时候要关注可能会抛出的异常。

小结

从编程语言的历史进程看Kotlin,它是现代化的编译型、强类型、静态语言,符合语言多编程范式的发展潮流。语言特性相比Java更加函数式,并把一些Java编程的最佳实践沉淀到语言特性中。

收银台原生化对编程语言的选型,是基于对运行效率和开发效率之间的权衡;Kotlin是工具,正确的使用工具有助于我们更好地表达收银台的业务逻辑。使用Kotlin的过程是对过去Java编程思维进化的过程,这是Kotlin带来的额外收益。

收银台落地Kotlin过程中,我们消除了空指针异常,截止目前收银台自身业务代码没有空指针的异常。Kotlin原生化改造后,进入首页加载完成耗时由原来H5收银台1180ms左右到现在的360ms左右,渲染时间缩短了820ms,首屏加载时间缩短了69.5%。

学习分享

在当下这个信息共享的时代,很多资源都可以在网络上找到,只取决于你愿不愿意找或是找的方法对不对了

很多朋友不是没有资料,大多都是有几十上百个G,但是杂乱无章,不知道怎么看从哪看起,甚至是看后就忘

如果大家觉得自己在网上找的资料非常杂乱、不成体系的话,我也分享一套给大家,比较系统,我平常自己也会经常研读。

2020最新上万页的大厂面试真题

七大模块学习资料:如NDK模块开发、Android框架体系架构…

只有系统,有方向的学习,才能在段时间内迅速提高自己的技术。

这份体系学习笔记,适应人群:
**第一,**学习知识比较碎片化,没有合理的学习路线与进阶方向。
**第二,**开发几年,不知道如何进阶更进一步,比较迷茫。
第三,到了合适的年纪,后续不知道该如何发展,转型管理,还是加强技术研究。如果你有需要,我这里恰好有为什么,不来领取!说不定能改变你现在的状态呢!
由于文章内容比较多,篇幅不允许,部分未展示内容以截图方式展示 。如有需要获取完整的资料文档的朋友点击我的GitHub免费获取。

京东APP收银台Kotlin化实践相关推荐

  1. 京东APP鸿蒙版开发实践,有点牛逼哦!

    京东鸿蒙版来了〜 背景 随着鸿蒙2.0的发布,华为部分手机用户迎来鸿蒙时代,京东作为华为鸿蒙OS的合作APP,首次投入鸿蒙应用商用版开发,目前已上架V10.0.2版本. 鸿蒙OS特性 2021年6月3 ...

  2. 鸿蒙版开发实践,有点牛逼哦!- 京东APP

    京东APP鸿蒙版开发实践,有点牛逼哦! 程序IT圈 今天 以下文章来源于京东零售技术 ,作者侯伟浩 狄彩林 京东零售技术 京东零售那些事,有品.有调又有料的研发资讯,带你深入了解程序猿的生活和工作. ...

  3. android高仿京东app

    仿京东app 采用组件化架构 屏幕适配方案可以较好解决多分辨率及同分辨率不同dpi适配: 全新组件化架构升级,相比之前的方案模块间更为解耦且使用更为方便: 本项目为仿京东项目,资源为抓包获取,项目框架 ...

  4. 京东App Swift 混编及组件化落地

    背景 自 Swift 诞生以来,逐步见证其从饱受诟病到日渐完善.在苹果的全力推动下,潜移默化地把开发支持中心从 Objective-C 转向 Swift,在业界的呼声也越演越烈.当我们相继迎来 ABI ...

  5. 开发嵌入京东app h5| Hybrid | 微信小程序 | 实践踩坑总结十六条

    一 前言 笔者最近一直在开发京东app嵌入的h5项目和微信小程序商城项目,在此期间遇到很多坑.这篇文章主要是针对 h5| Hybrid | 微信小程序 三个方向来讲述我遇到的坑,以及详细讲解我是如何解 ...

  6. 京东鸿蒙版来了!京东 APP HarmonyOS 开发实践!

    点击"开发者技术前线",选择"星标????" 让一部分开发者看到未来 来自:京东零售技术 京东鸿蒙版来了〜 背景 随着鸿蒙2.0的发布,华为部分手机用户迎来鸿蒙 ...

  7. 京东APP百亿级商品与车关系数据检索实践 | 京东云技术团队

    导读 本文主要讲解了京东百亿级商品车型适配数据存储结构设计以及怎样实现适配接口的高性能查询.通过京东百亿级数据缓存架构设计实践案例,简单剖析了jimdb的位图(bitmap)函数和lua脚本应用在高性 ...

  8. 京东java前后端联调_前端工程化、组件化实践JDM分享

    前端技术原创文 前端工程化.组件化实践JDM分享 该文由孵化创新一部曾瑞文在研究院技术分享会的分享内容总结而成,主要讲解了团队创新的前端工程化.组件化的思想及实践应用. 为什么要搞前端框架? Java ...

  9. 京东MySQL数据库Docker化最佳实践(附PPT)

    讲师介绍   刘风才 京东资深数据库专家 2012年加入京东,担任MySQL DBA一职,负责数据库架构设计.数据库性能优化等日常运维工作,参与过分布式数据库项目.多中心交易项目等. 2013~201 ...

最新文章

  1. Win7 怎么取消禁(被)ping
  2. VDI序曲九 实战体验Remote FX(重磅推荐)
  3. 路由器固件下的小试牛刀,与漏洞相关的经验分享
  4. android设置gradle位置,android studio gradle 位置更改
  5. 在Ubuntu下成功搭建以太坊私有链挖矿并转账
  6. matlab神经网络工具箱创建神经网络,matlab神经网络工具箱创建神经网络
  7. centos 下使用sublime
  8. 调用反射类的指定方法
  9. 查询计算机专业及选修了英语的学生,实验五 数据库综合查询(学生)
  10. JDBC连接数据库(一)
  11. 中缀表达式转换为前缀或后缀表达式的手工做法
  12. Python与数据库(2)Oracle
  13. SpringBoot集成MongoDB
  14. ML-Agents案例之金字塔
  15. 重看经典动漫《火影忍者》的一些感受
  16. C/C++ 机房预约系统
  17. outer apply的用法
  18. ableton live10中文版|音乐制作软件 附安装教程
  19. i 技术会笔记 | Druid在爱奇艺的实践和技术演进
  20. android 九宫格图案解锁

热门文章

  1. php递归执行,php递归算运行流程解析法实例演示
  2. AR行业发展现状:定义、技术原理及商业价值
  3. Boarding Passes
  4. 用 Python 人脸识别,选抖音上好看的小姐姐
  5. 怎么去掉WORD中的回车字符
  6. RedisTemplate中list类型的使用
  7. PHP函数array_flip
  8. 小米科技-瞿晋萍-米聊技术选型与架构
  9. hbuilderX 移动网页如何在手机查看,扫码预览打不开
  10. 2021秋招面试 吉利 凉经