Kotlin介绍 (公司分享)
前言
我是2016年年初开始接触Kotlin,中旬的时候开始项目中开始使用,到后来一发不可收拾,项目全部使用Kotlin。以前在用java开发的时候,因为只用过C,C++,OC还有一些脚本语言,所以觉得java还是挺好的,一直用反射和注解等把项目代码做封装做减法,觉得很棒。
image.png
后来用Swift体验过语法糖带来的快感,当遇到大牛给我介绍了Scala的时候,我才震惊,卧槽Java还可以这样写。于是开始关注可以用来写安卓的敏捷开发语言。当然刚开始尝试的是Scala,Groovy.但是最终还是失败了。然后开始接触Kotlin,当时的官网上主打的就是"可以和JAVA 100%混编的用于安卓开发语言",然后他有官方提供的anko库和Extend的studio插件。所以决定开始尝试用kotlin。
Kotlin是什么
它是一门jvm语言,函数式的敏捷开发语言。当然上面提到的 Scala,Groovy,JRuby等等都是这类语言。前期官网在介绍语言的时候,主要是针对安卓开发。但是现在的介绍如下图
静态与动态编程语言
静态语言是在编译时变量的数据类型即可确定的语言,多数静态类型语言要求在使用变量之前必须声明数据类型。 例如:C++、Java、Delphi、C#等。
动态语言是在运行时确定数据类型的语言。变量使用之前不需要类型声明,通常变量的类型是被赋值的那个值的类型。 例如JavaScript等等。
构建平台
image.png
当然今天主要介绍的用Kotlin做安卓开发
为什么要用Kotlin
Java用的好好的,为什么要用Kotlin呢?来看看官方的解释
1. 简洁(大大减少样板代码的数量)
Kotlin的简洁得益与它的语法糖,大量的脚本语言的特性可以让我们的代码变得冰清玉洁。例如
// Data class 数据类 dto vo都可以使用 大量的数据类 会让你的responseBo类会变得异常简洁
data class User(val name: String, val age: Int = 12)
val jane = User("Jane", 35)
val jane1 = User("Jane", 35)
//浅拷贝 Kotlin 1.2 中已弃用
val jane2 = jane.copy(age=10)
//输出结果 true false 10
System.out.println("${jane.equals(jane1)} ${jane.equals(jane2)} ${jane2.age}")
//用元组 做解构的动作
val (name, age) = jane
//闭包 利用Kotlin闭包的语法糖,可以让你的代码随心所遇 <当心逃逸闭包的内存泄露>
//当然系统提供的一些函数
["","","","",""].forEeach{ it }
repeat(10){ }
val sortArr = oldArray.sort{a,b -> a.id > b.id }
//自己封装例如
ui(3){ //3秒后用主线程做什么 }
cutDown(60){ sec -> //倒计时60秒做什么 }
view.onClick{ }
//Auko的让安卓的布局更简单
textView {
gravity = Gravity.CENTER
textSize = DimensAdapter.textSpSize(CustomTSDimens.NORMAL)
textColor = Color.WHITE
backgroundResource = R.drawable.goods_price_bg
}.lparams {
alignParentBottom()
alignParentRight()
horizontalMargin = kIntWidth(0.02f)
verticalMargin = kIntHeight(0.02f)
}
//当然anko也提供了一些其他的语法糖
fun getUsers(db: ManagedSQLiteOpenHelper): List<User> = db.use {
db.select("Users")
.whereSimple("family_name = ?", "John")
.doExec()
.parseList(UserParser)
}
startActivity<MAcitity>("传参1":"" , "传参2":12 , ...... )
//利用尾随闭包的特性 dsl风格的代码 例如球酷的网络请求
post(地址){
header{ }
body{
request{
header{}
body{}
}.aes256()
}
}
//或者做成链式调用的方法
post(地址).header{}.body{}.aes256().excute()
image.png
//运算符重载 做表单的构建
form {
+ InputCell
+ DateCell
+ ChooseCell
+ PhotoCell
}
//Preferences 偏好
preferences {
+ userCell("用户名")
+ userCell("企业名")
+ userCell("密码名")
+ PhotoCell("身份证")
}
//利用委托的语法 做一些数据的后置处理
var userName: String by SharePrefenceDelegate()
var newsData:Array<News> by CacheDelegate()
val lazyValue: String by lazy { "属性懒加载" }
//单例 object关键字
object ThisIsASingleton {
val companyName: String = "张三"
}
2. 安全 (主要避免空指针异常)
这里主要说的就是 Optional. 避免空指针有一句经典『不传空就不会有空指针出现』
var b: String? = "abc"
b?.toString()
//相当于java的
if( b != null) { b.toString() }
//Elvis 操作符 做默认值处理
val length = b?.length ?: 0
//也可以类型转换
(act as? Content).startActivity<MActivity>()
//支持空数组
val nullableList: List<Int?> = listOf(1, 2, null, 4)
val intList: List<Int> = nullableList.filterNotNull()
3. 互操作性 (充分利用 JVM、Android 和浏览器的现有库)
这里说的就和java的无缝对接,可以请求java的方法,第三方库,甚至不需要桥接。java也可以使用kt定义的方法和属性。
//官方给出了调用rxjava例子
Flowable
.fromCallable {
Thread.sleep(1000)
"Done"
}
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.single())
.subscribe(::println, Throwable::printStackTrace)
Kotlin 对一些Java 类型做了特殊的映射处理
Java 类型 Kotlin 类型
byte kotlin.Byte
short kotlin.Short
int kotlin.Int
集合的映射
只读的属性方便分层开发的时候,防止上层操作下层的数据
//伴生对象
class C {
companion object {
@JvmStatic fun foo() {}
fun bar() {}
}
}
4. 工具友好(可用任何 Java IDE 或者使用命令行构建。)
工具不友好,难道会有人会用记事本或者命令行写吗?
当然这里指的是开发工具的一些插件支持,无论是在线,还是本地的工具 还是 开发工具(idea , eclipse)都很好的支持。
提到工具,这里提到官方的库支持也很好,在我接触的时候安卓的库已经支持的不错,如下:
选择Kotlin的好处
1. 越少的代码,实现越多的功能
给我带来的是开发思路的改变,以前我关注的是交互,界面展示,尤其是material设计规范出来后,卧槽还能这样。但是现实的项目由不得我们胡作非为,有UE UX UI 还有产品在,所以交互交给他们,我们按照规则做事情,我们要做的是敏捷开发。
一行代码,一个脑细胞
代码少不仅仅是开发快,改bug也快。
这时候有人要问了,能少多少代码?我个人实践至少少50%的代码,最关键的是语法糖会让你兴奋不已,你会停不下来不断精简你的代码。
2. 优雅的代码实现
何为优雅?完成功能开发已经不是本质问题了,如果能在开发的同时,把代码写的很优雅将会增加自己的代码乐趣。几年后回来看自己的代码,会不尽感叹:当时我那么屌
//例如1.1的新特性 协程
//要实现的效果 异步处理效果 handler Rxjava EventBus
AsyncTask{
pre(){ 界面提示我要插入几万条数据 }
int doingBackgroud(){ 插入数据 }
post(Int num){ 提示用户插入多少条数据 }
}.excute()
//协程处理 类似于 java的future
val 异步任务 = async(CommonPool,false) {
//需要线程中执行的代码块
}
//上面的异步任务 参数false 说明需要调用 await()方法区启动这个任务
launch(UI) { val 返回值 = 异步任务.await() }
//也可以用函数
suspend fun insert(foos: [Foo]): Int {
……
}
async {
// 界面提示
val num = insert(???)
// 界面提示
}
当然代码的优雅还有很多,例如装载网路请求参数
AppConfig config = new AppConfig()
config.属性1 = ?
config.属性2 = ?
config.属性3 = ?
config.属性4 = ?
config.属性5 = ?
val config = AppConfig().apply{
属性1 = ?
属性2 = ?
属性3 = ?
属性4 = ?
属性5 = ?
}
//参数通过元组传参
requestOrders("pageSize" to 10,"pageNo" to 1,"userID" to "张三")
3. 注入
分层开发必然遇到依赖注入的问题。不在Dagger来配置实例工厂类,也不需要配置实例的生命周期
// 用接口的扩展可以 简单粗暴的实现注入的方法
interface UserDao {
func login(){}
func modifyPW(){}
func uploadFace(){}
}
//如何让表层 用到UserDao的实现类 这个就需要注入
interface UserProcessAble {
var userDao:UserDao
get() = AopInvocation<AppDao>(impl).bind(UserDao::class.java)
}
//这样界面如果想做User的操作
class MainActivity : Activity, UserProcessAble {
func login(){
userDao.login()
}
}
有什么缺点
想到这个问题的时候,我特意去百度一下。因为我觉得没什么确定,除了不支持宏,结构体,还有尾随闭包多参数的时候 不能像swift一样 $1 $2 $3...这样下去。
不知道运算符的构建,不能让代码秀得飞起!!!
//加载图片
imageView <=== "网址"
//路由调整
--> MActivity.class <== "title" to 标题
网上说:
1.编译速度慢 对于从eclipse走过来的安卓开发,我连Ant的构建速度都不介意,你觉得我会介意那点编译速度?
- 没有静态修饰语 其实我觉得是好处,大量的静态对于项目的结构并不是什么好处,而且有伴生对象,top-level也不止是class,而是文件,所以静态数据 要多少有多少
小众 小众 小众 重要的事情说三遍
小众的技术得不到大众的支持,虽然kotlin以前在1年前就被官方作为推荐语言,但是使用的人少之又少。
面试官1: "对不起,我们不用。"
面试官2: "来聊聊你看过的一些库的理解"
"我看过anko库 .......",
面试官2: "来聊聊java的一些库呢? rxjava, databinding dagger2 eventBus ORM框架..."
面试官2: "你这深度不够啊 不好意思"
我有语法支持,为什么要看第三方库源码呢?就好像 我可以nio做连接,为什么还要用netty/mina的框架呢?
一番介绍后
面试官3: "来聊聊java的一些知识"
面试官4:"我们项目都是java写的,kt的代码不好接啊"
对,没有市场,虽然无缝对接,coding质量得到质的飞跃,但是尝试的人还是很少。如果你喜欢语法糖带来的开发乐趣,可以尝试下~~
手机开发的事业线很短,且行且珍惜~~