kotlinAndroid开发之路其他

说那么多干嘛,直接用kotlin写项目吧

2017-06-26  本文已影响756人  间歇性丶神经病患者

Kotlin 与 Android

什么是Kotlin?

Kotlin,它是JetBrains开发的基于JVM的语言。JetBrains因为创造了一个强大的Java开发IDE被大家所熟知。Android Studio,官方的Android IDE,就是基于Intellij,作为一个该平台的插件。
Kotlin是使用Java开发者的思维被创建的,Intellij作为它主要的开发IDE。对于Android开发者,有两个有趣的特点:
对Java开发者来说,Kotlin是非常直觉化的,并且非常容易学习。语言的大部分内容都是与我们知道的非常相似,不同的地方,它的基础概念也能迅速地掌握它。
它与我们日常生活使用的IDE无需配置就能完全整合。Android Studio能够非常完美地理解、编译运行Kotlin代码。而且对这门语言的支持来正是自于开发了这个IDE的公司本身,所以我们Android开发者是一等公民。
但是这仅仅是开发语言和开发工具之间的整合。相比Java 7的优势到底是什么呢?

  1. 它更加易表现:这是它最重要的优点之一。你可以编写少得多的代码。
  2. 它更加安全:Kotlin是空安全的,也就是说在我们编译时期就处理了各种null的情况,避免了执行时异常。如果一个对象可以是null,则我们需要明确地指定它,然后在使用它之前检查它是否是null。你可以节约很多调试空指针异常的时间,解决掉null引发的bug。
  3. 它是函数式的:Kotlin是基于面向对象的语言。但是就如其他很多现代的语言那样,它使用了很多函数式编程的概念,比如,使用lambda表达式来更方便地解决问题。其中一个很棒的特性就是Collections的处理方式。
  4. 它可以扩展函数:这意味着我们可以扩展类的更多的特性,甚至我们没有权限去访问这个类中的代码。
  5. 它是高度互操作性的:你可以继续使用所有的你用Java写的代码和库,因为两个语言之间的互操作性是完美的。甚至可以在一个项目中使用Kotlin和Java两种语言混合编程。

Kotlin的用途

服务器端

使用 Kotlin 进行服务器端开发
Kotlin 非常适合开发服务器端应用程序,允许编写简明且表现力强的代码, 同时保持与现有
基于 Java 的技术栈的完全兼容性以及平滑的学习曲线:
表现力: Kotlin 的革新式语言功能,例如支持类型安全的构建器和委托属性,有助于构建
强大而易于使用的抽象。
可伸缩性: Kotlin 对协程的支持有助于构建服务器端应用程序, 伸缩到适度的硬件要求
以应对大量的客户端。
互操作性: Kotlin 与所有基于 Java 的框架完全兼容,可以让你保持熟悉的技术栈,同时
获得更现代化语言的优势。
迁移: Kotlin 支持大型代码库从 Java 到 Kotlin 逐步迁移。你可以开始用 Kotlin 编写新代
码,同时系统中较旧部分继续用 Java。
工具: 除了很棒的 IDE 支持之外,Kotlin 还为 IntelliJ IDEA Ultimate 的插件提供了框架特
定的工具(例如 Spring)。
学习曲线: 对于 Java 开发人员,Kotlin 入门很容易。包含在 Kotlin 插件中的自动 Java
到 Kotlin 的转换器有助于迈出第一步。Kotlin 心印 通过一系列互动练习提供了语言主要
功能的指南。

服务器推荐的框架

Spring 利用 Kotlin 的语言功能提供更简洁的 API, 从版本 5.0 开始。在线项目生成器允
许用 Kotlin 快速生成一个新项目。
Vert.x 是在 JVM 上构建响应式 Web 应用程序的框架, 为 Kotlin 提供了专门支持,包括
完整的文档。
Ktor 是由 JetBrains 构建的 Kotlin 原生 Web 框架,利用协程实现高可伸缩性,并提供易
于使用且合乎惯用法的 API。
kotlinx.html 是可在 Web 应用程序中用于构建 HTML 的 DSL。 它可以作为传统模板系统
(如JSP和FreeMarker)的替代品。
通过相应 Java 驱动程序进行持久化的可用选项包括直接 JDBC 访问、JPA 以及使用
NoSQL 数据库。 对于 JPA,kotlin-jpa 编译器插件使 Kotlin 编译的类适应框架的要求。
ktor - 用 Kotlin 写的 Web 后端开发框架
Kara - MVC 开发框架
Yested - 用来开发 SPA 应用的框架
HEXAGON- 微服务框架

Android 端

Kotlin 非常适合开发 Android 应用程序,将现代语言的所有优势带入 Android 平台而不会引入
任何新的限制:
兼容性:Kotlin 与 JDK 6 完全兼容,保障了 Kotlin 应用程序可以在较旧的 Android 设备
上运行而无任何问题。Kotlin 工具在 Android Studio 中会完全支持,并且兼容 Android 构
建系统。
性能:由于非常相似的字节码结构,Kotlin 应用程序的运行速度与 Java 类似。 随着
Kotlin 对内联函数的支持,使用 lambda 表达式的代码通常比用 Java 写的代码运行得更
快。
互操作性:Kotlin 可与 Java 进行 100% 的互操作,允许在 Kotlin 应用程序中使用所有现
有的 Android 库 。这包括注解处理,所以数据绑定和 Dagger 也是一样。
占用:Kotlin 具有非常紧凑的运行时库,可以通过使用 ProGuard 进一步减少。 在实际
应用程序中,Kotlin 运行时只增加几百个方法以及 .apk 文件不到 100K 大小。
编译时长:Kotlin 支持高效的增量编译,所以对于清理构建会有额外的开销,增量构建通
常与 Java 一样快或者更快。
学习曲线:对于 Java 开发人员,Kotlin 入门很容易。包含在 Kotlin 插件中的自动 Java
到 Kotlin 的转换器有助于迈出第一步。Kotlin 心印 通过一系列互动练习提供了语言主要
功能的指南。

Android 推荐使用的工具

Kotlin Android 扩展是一个编译器扩展, 可以让你摆脱代码中的 findViewById() 调用,
并将其替换为合成的编译器生成的属性。
Anko 是一个提供围绕 Android API 的 Kotlin 友好的包装器的库,以及一个可以用 Kotlin
Kotlin 用于 Android 代码替换布局 .xml 文件的 DSL。
KAndroid - Kotlin library for Android
Bubble - 屏幕方向监测
Kotpref -android sp缓存工具
Fuese - android内存缓存工具
Kotter Knife KotlinPoet 类似黄油刀的依赖注入框架
Klaxon 一个解析 JSON 的库

Kotlin 与 JavaScript

Kotlin 提供了 JavaScript 作为目标平台的能力。它通过将 Kotlin 转换为 JavaScript 来实现。
目前的实现目标是 ECMAScript 5.1,但也有最终目标为 ECMAScript 2015的计划。
当你选择 JavaScript 目标时,作为项目一部分的任何 Kotlin 代码以及 Kotlin 附带的标准库都
会转换为 JavaScript。 但是,这不包括使用的 JDK 和任何 JVM 或 Java 框架或库。任何不是
Kotlin 的文件会在编译期间忽略掉。
Kotlin 编译器努力遵循以下目标:
提供最佳大小的输出
提供可读的 JavaScript 输出
提供与现有模块系统的互操作性
在标准库中提供相同的功能,无论是 JavaScript 还是 JVM 目标(尽最大可能程度)。

怎么使用kotlin(环境搭建)

IDEA:

Kotlin版本从2015年开始就与IntelliJ IDEA捆绑在一起,

  1. 在安装IntelliJ IDEA后,打开它并创建一个新项目。选择菜单:【File】->【New Project】,Java Module并选择SDK,Kotlin要与JDK 1.6+一起使用。 另外,选择Kotlin(Java)复选框。


    image.png
  2. 点击finish就可以,如下图:


    image.png

AndroidStudio

好吧,其实IDEA怎么搭建环境不关我什么事,as搭建环境才是关我事情的

  1. 安装Kotlin的插件:


    image.png
  1. 把项目转换为kotlin项目:


    image.png
  1. 新建好的MainActivity.java, 注意这里是.java后缀的java文件,我们可以手动转换为kotlin代码


    image.png
image.png

4,转换后得到了一个MainActivity.kt,


image.png

到了这一步我们就拿到了一个原汁原味的kotlin项目了。

image.png

基本的语法:

基本类型:

数字

image.png

定义数字:

var aInt:Int=1
var bDouble:Double=12.5
var fFloat=12.4f

每个数字类型支持如下的转换:


toByte(): Byte
toShort(): Short
toInt(): Int
toLong(): Long
toFloat(): Float
toDouble(): Double
toChar(): Char

也可以有隐式的转换:

val l = 1L + 3 // Long + Int => Long

也支持运算符:

这是完整的位运算列表(只用于 Int 和 Long ):
shl(bits) – 有符号左移 (Java 的 << )
shr(bits) – 有符号右移 (Java 的 >> )
ushr(bits) – 无符号右移 (Java 的 >>> )
and(bits) – 位与
or(bits) – 位或
xor(bits) – 位异或
基本类型
56
inv() – 位非

字符

字符用 Char 类型表示。它们不能直接当作数字

我们可以显式把字符转换为 Int 数字:

fun decimalDigitValue(c: Char): Int {
if (c !in '0'..'9')
throw IllegalArgumentException("Out of range")
return c.toInt() - '0'.toInt() // 显式转换为数字
}

其他的就没什么了.....不讲了

控制流

if else

在 Kotlin 中, if 是一个表达式,即它会返回一个值。 因此就不需要三元运算符(条件 ? 然
后 : 否则),因为普通的 if 就能胜任这个角色。

eg. 有一个int值是a,一个int值是b,求他们的比较大的那个数

java


 int a = 1, b = 3;
 Log.e("a和b的最大值是", a > b ? a + "" : b + "");

kotlin

 val a:Int=1
 val b:Int=3
 val max = if (a > b) a else b
 print("a和b里面最大的是"+max)

When 表达式

when 将它的参数和所有的分支条件顺序比较,直到某个分支满足条件。 when 既可以被当
做表达式使用也可以被当做语句使用。如果它被当做表达式, 符合条件的分支的值就是整个
表达式的值,如果当做语句使用, 则忽略个别分支的值。(像 if 一样,每一个分支可以是
一个代码块,它的值是块中最后的表达式的值。)
如果其他分支都不满足条件将会求值 else 分支。 如果 when 作为一个表达式使用,则必须
有 else 分支, 除非编译器能够检测出所有的可能情况都已经覆盖了。

eg. 实例demo里面的适配器代码:


  when (dataItem.type) {
            "Android" -> holder?.ivType?.setImageResource(R.mipmap.android_icon)
            "iOS" -> holder?.ivType?.setImageResource(R.mipmap.ios_icon)
            "前端" -> holder?.ivType?.setImageResource(R.mipmap.js_icon)
            "拓展资源" -> holder?.ivType?.setImageResource(R.mipmap.other_icon)
            else -> holder?.ivType?.setImageResource(R.mipmap.android_icon)
        }

For 循环

for 循环可以对任何提供迭代器(iterator)的对象进行遍历,语法如下:


for (item in collection) print(item)

While 循环

循环中的Break和continue

--- --- 可以参考下我后面发出来的文档

定义一个类:

类声明由类名类头(指定其类型参数、主构造函数等)和由大括号包围的类体构成。类头
和类体都是可选的; 如果一个类没有类体,可以省略花括号。


class Person constructor(firstName: String) {
}

构造函数

在 Kotlin 中的一个类可以有一个主构造函数和一个或多个次构造函数。主构造函数是类头的
一部分:它跟在类名(和可选的类型参数)后。

class Person constructor(firstName: String) {
}

如果主构造函数没有任何注解或者可见性修饰符,可以省略这个 constructor 关键字。

class Person(firstName: String) {
}

定义一个构造函数的函数体:

class Person(name: String, surname: String) {
    init{
        ...
    }
}

很复杂...看懵了,不管了 我们看个例子:


/**
 * Created by Ly on 2017/6/23.
 */
open class Person(var age: Int, var name: String) {
    fun sayName(): String {
        return name
    }
    fun sayAge(): Int {
        return age
    }
}
fun main(args: Array<String>) {
    val person = Person(11, "Ly")
    print(person.sayName()+" is "+person.sayAge())
}

打印结果如下:

image.png

修改代码


open class Person(var age: Int, var name: String) {

    init {
        name="Lht"
        age=24
    }
    fun sayName(): String {
        return name
    }
    fun sayAge(): Int {
        return age
    }
}
fun main(args: Array<String>) {
    val person = Person(11, "Ly")
    print(person.sayName()+" is "+person.sayAge())
}

打印结果:

image.png

eg. Android 适配器的ViewHolder类(java 代码)


  public static class ViewHolder extends RecyclerView.ViewHolder {
        @BindView(R.id.iv_girl)
        ImageView ivGirl;
        public ViewHolder(View itemView) {
            super(itemView);
            KnifeKit.bind(this, itemView);
        }
    }


Android适配器的ViewHolder类(Kotlin代码)


    inner class GirlHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        internal var ivGril: ImageView = itemView.findViewById(R.id.iv_girl)
    }

Android适配器的ViewHolder类(Kotlin代码 不用缩写 使用init初始化方法)


 inner class HomeHolder(item: View) : RecyclerView.ViewHolder(item) {
        internal var ivType: ImageView
        internal var tvType: TextView
        internal var ivAuthor: ImageView
        internal var tvAuthor: TextView
        internal var tvTime: TextView
        internal var rlMessage: RelativeLayout
        internal var ivPart: ImageView
        internal var ivVedio: ImageView
        internal var tvItem: TextView

        init {
            ivType = itemView.findViewById<ImageView>(R.id.iv_type)
            tvType = itemView.findViewById<TextView>(R.id.tv_type)
            ivAuthor = itemView.findViewById<ImageView>(R.id.iv_author)
            tvAuthor = itemView.findViewById<TextView>(R.id.tv_author)
            tvTime = itemView.findViewById<TextView>(R.id.tv_time)
            rlMessage = itemView.findViewById<RelativeLayout>(R.id.rl_message)
            ivPart = itemView.findViewById<ImageView>(R.id.iv_part)
            ivVedio = itemView.findViewById<ImageView>(R.id.iv_vedio)
            tvItem = itemView.findViewById<TextView>(R.id.tv_item)
        }
    }

class的继承:

默认下任何类都是继承自Any( 类似 java中的Object,但是Any 不是 java.lang.Object ;尤其是,它除了 equals() 、 hashCode() 和 toString() 外没有任何成员) ,但是我们可以继承其它类。
所有的类默认都是不可继承的(final),所以我们只能继承那些明确声明open或者abstract的类:

image.png
open class Animal(name: String)
class Person(name: String, surname: String) : Animal(name)

当我们只有单个构造器时,我们需要在从父类继承下来的构造器中指定需要的参数。这是用来替换Java中的super调用的。
其实就是super()

字段和属性

类里面有属性,属性可以用关键字 var 声明为可变的,否则使用只读关键字 val

kotlin中的函数:

函数(方法)可以使用fun关键字进行定义:

fun onCreate(savedInstanceState: Bundle?) {
}

如果你没有指定它的返回值,它就会返回Unit,与Java中的void类似,但是Unit是一个真正的对象。你当然也可以指定任何其它的返回类型:

fun add(x: Int, y: Int) : Int {
    return x + y
}

然而如果返回的结果可以使用一个表达式计算出来,你可以不使用括号而是使用等号:

fun add(x: Int,y: Int) : Int = x + y

我们可以给参数指定一个默认值使得它们变得可选

fun toast(message: String, length: Int = Toast.LENGTH_SHORT) {
    Toast.makeText(this, message, length).show()
}

这个给我的感觉就类似这个:

 @RequestMapping(value = "updateType")
public String updateType(
 @RequestParam(value = "typeId", defaultValue = "", required = false) Integer typeId,
 @RequestParam(value = "typeName", defaultValue = "", required = false) String typeName,
 @RequestParam(value = "flag", defaultValue = "1", required = false) Integer flag,
 @RequestParam(value = "type", required = false) Integer typeAttributes,
 HttpServletRequest request, Model model) {

kotlin中的接口:

android的接口一般用于做回调地狱

   interface ItemClickListener {
        fun onItemClickListener(url:String)
    }

使用点击事件回调地狱


  girlAdapter?.setOnItemClickListener(object : GirlAdapter.ItemClickListener {
            override fun onItemClickListener(url: String) {
                val intent = Intent()
                val bun = Bundle()
                bun.putString("url", url)
                //获取intent对象
                intent.setClass(activity, SeeBeautyActivity::class.java)
                // 获取class是使用::反射
                intent.putExtra("extra", bun)
                startActivity(intent)
            }
        })

kotlin 中的内部类

使用inner关键字


/**
 * Created by Ly on 2017/6/23.
 * 美女合集适配器
 */
class GirlAdapter(context: Context) : RecyclerView.Adapter<GirlHolder>() {
    private var data = ArrayList<GankResults.Item>()
    private var context: Context = context
    private var onItemClickListener: ItemClickListener? = null
    fun setOnItemClickListener(onItemClickListener: ItemClickListener) {
        this.onItemClickListener = onItemClickListener
    }

    fun setData(data: List<GankResults.Item>) {
        this.data.clear()
        this.data.addAll(data)
        notifyDataSetChanged()
    }

    fun addData(data: List<GankResults.Item>) {
        this.data.addAll(data)
        notifyDataSetChanged()
    }

    override fun onBindViewHolder(holder: GirlHolder?, position: Int) {
        Glide.with(context).load(data[position].url).into(holder?.ivGirl)
        holder?.itemView?.setOnClickListener {
            onItemClickListener?.onItemClickListener(data[position].url)
        }
    }

    override fun getItemCount(): Int = data.size

    override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): GirlHolder {
        return GirlHolder(LayoutInflater.from(context).inflate(R.layout.adapter_gril, parent, false))
    }

    inner class GirlHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        internal var ivGirl: ImageView = itemView.findViewById(R.id.iv_girl)
    }

    interface ItemClickListener {
        fun onItemClickListener(url:String)
    }
}


OK 大概了解了kotlin以后,我们进入正题,kotlin与android

划重点:

  1. 和Java的无缝调用,说明我们使用kotlin代码也可以随意使用目前所有的第三方java语言的sdk
  2. 大量的语法糖,例如Toast 吐司
  3. 更加安全,Kotlin 并不存在NullPointException
  4. RxKotlin

按着两个项目对比讲,主要讲区别 以及anko

OK,开始之前,我们先看两个demo项目:
https://github.com/LinHuanTanLy/JavaDemo
https://github.com/LinHuanTanLy/KotlinDemo

image.png image.png
上一篇下一篇

猜你喜欢

热点阅读