2017-07-13 18:53:53 wxz1179503422 阅读数 493
  • 为什么Kotlin是你下一个要掌握的语言?

    Kotlin教程:Kotlin是一门与Swift类似的静态类型JVM语言,由JetBrains设计开发并开源。与Java相比,Kotlin的语法更简洁、更具表达性,而且提供了更多的特性,比如,高阶函数、操作符重载、字符串模板。它与Java高度可互操作,可以同时用在一个项目中。本课程结合讲师的实践案例为同学们深度讲解Java转kotlin需要知道的一些事。

    5568 人正在学习 去看看 CSDN讲师

Kotlin和Swift的一些异同点
这里写图片描述

2017-10-23 09:58:16 brycegao321 阅读数 2493
  • 为什么Kotlin是你下一个要掌握的语言?

    Kotlin教程:Kotlin是一门与Swift类似的静态类型JVM语言,由JetBrains设计开发并开源。与Java相比,Kotlin的语法更简洁、更具表达性,而且提供了更多的特性,比如,高阶函数、操作符重载、字符串模板。它与Java高度可互操作,可以同时用在一个项目中。本课程结合讲师的实践案例为同学们深度讲解Java转kotlin需要知道的一些事。

    5568 人正在学习 去看看 CSDN讲师

       Kotlin是Android的最新开发语言;

       Swift是iOS的最新开发语言;

       二者语法很像, 下面就对比一下。

       Kotlin中文网站:     https://www.kotlincn.net/docs/reference/basic-syntax.html

 按官方文档顺序说明:

功能

Kotlin

Swift

说明

定义包

package com.*.*                                                               实例:pacakge com.brycegao.test

import *                                                         实例: import UIKit

1Kotlin声明定义包跟Java相同,包名必须是小写字母;                                  2Swift引用库时使用import关键字。

引用类

import *.*.*                                                                          实例:import java.util.*

只需引用库

KotlinJava相同, Swift不需要引用类、只需要引用库即可;

定义函数

fun sum(a: Int, b: Int): Int {           

    return a + b    

}                                                                                        如果函数体只有一行代码,可以简写函数。                     fun sum(a: Int, b: Int): Int = a + b                                      调用方法: sum(1, 2)

func sum(label1 a: Int, label2 b: Int)->Int { return a + b}                                                                调用方式: sum(lable1: 1, label2: 2)

1Kotlin使用fun作为函数关键字;  2func使用func作为函数关键字;  3Kotlin使用:分隔参数和返回值类型; 4Swift使用->分隔参数和返回值类型;

可变参数

var关键字           举例: var a: Int = 1

   var关键字      举例: var a: Int = 1                  var b: Int       //可以不赋值

KotlinSwift都是用var关键字声明可变参数,参数值可修改且声明时不必赋值。

常量参数

val关键字           举例: val a: Int = 1

 let关键字            举例: let a: Int = 1

声明时必须要赋值,而且参数值不可改

注释

//一行注释                                                                                 /*多行注释*/

//一行注释                                                                                 /*多行注释*/

SwiftKotlin注释方法相同

字符串模板

var a = 1                                                                           var s1 = “a is $a”    //用双引号包含起来 $后面跟着参数        a = 2                                                                                  val s2 =  “${s1.replace(“is”, “was”)}, but now is $a”

var a = 1

var s1 = "a is \(a)"

a = 2

let s2 = "\(s1.replacingOccurrences(of: "is", with: "was")), but now is \(a)"

1Kotlin使用${}声明参数或者调用函数;                                                        2Swift使用\()包含参数;

转义

val s = “my name is \”zhangsan\” ”

let s = “my name is \”zhangsan\” “

使用\转义

if条件表达式

fun maxOf(a: Int, b: Int): Int {

    if (a > b) {

        return a

    } else {

        return b

    }

}                                                                                        或者 fun maxOf(a: Int, b: Int): Int = if (a > b) a  else b

func maxOf(label1 a: Int, label2 b: Int)->Int {

    if a > b {

        return a

    } else {

        return b

    }

}

if条件为真则进入函数体,为假进入else函数体

null

nil


可空值参数

在类型关键字后加问号,例如 var a: Int? = null

var a: Int? = nil

都使用问号表示参数可能为空

数组

    val arr1 = listOf("apple", "banana", "kiwi")

    val arr2 = byteArrayOf(1, 2, 3, 4)

    val arr3 = IntArray(5)

    val arr4 = FloatArray(5)

    val arr5 = DoubleArray(5)

    val arr6 = BooleanArray(5)

let array1 =[1, 2, 3, 4, 5]   //Int型数组

let array2: Array<Int> = Array()      //声明并定义了Int型数组

let array3:[Int] =[]     //声明并实例化Int型数组

let array4 = Array(repeating: 0, count: 5)   //数组有5个值,全是0

1Kotlin必须使用函数来定义数组; 2Swift定义数组更多样灵活;

遍历数组

    for(item in arr1){

        println(item)

    }

    //

    for(i in arr1.indices) {

        println(arr1[i])   //通过下标取值

    }

for item in array1 {

    print(item)

}

//

var i = 0

while i < array1.count {

    print(array1[i])

    i += 1

}

1、都支持for-in循环;                            2、通过下标遍历;

区间操作符

..为区间操作符,等价于[]                                                  举例:                                                                              for(i in 1..5) {

        print(i)      //输出12345

  }                                                                                          for (i in1..10 step 2) {
    print(i) 
//输出13579
}


为区间操作符,等价于[];  ..<等价于[)              for i in 1...5 {

    print(i)  //输出12345

}


for i in 1..<5 {

    print(i)   //输出1234

}

Kotlin支持设置步长step Swift步长只能是1.

语句分隔符

使用分号,默认不用写                                                          var o1 = 1;    //一行只能写一条语句
var o2 = 2


var o1 = 1;

var o2 = 2

都是用分号分隔,默认不用写

空返回值

Unit                                                                                     //返回值为空
fun method(): Unit {
   
}

fun method1() {


}

Void                                                              func method() -> Void {

    

}

//

func method1() {

    

}

函数返回值为空,可以省略返回值类型,或者使用UnitVoid关键字

//默认不支持继承,等同于Javafinal class

class SomeClass {

    

}


//使用open关键字,表示可继承的类

open class BasicClass constructor(name: String) {

    var value: String

    

    init {

        value = name     //主构造函数

    }                                                                                                                     //次构造函数必须调用主构造函数

    constructor(age: Int, name: String): this(name) {

        //函数体

    }

    //...属性方法

}


class Ext: BasicClass("basic") {

    //...属性、方法

}

class BasicClass {

    var name: String?

    var age: Int?

    

    init(param: String?) {  //构造函数

        name = param

        print("调用构造函数1 \(name)")

    }

    

    convenience init(age param1: Int, name param2: String) {

        self.init(param: param2)

        age = param1

    }

     //...属性和函数

    

    deinit {

        //析构函数

    }

}

let obj1 = BasicClass(age: 10, name: “zhangsan")                                                     //派生类

class Ext: BasicClass {

    //...属性和函数

}

1Kotlin类默认不支持继承,必须要用open关键字表示可继承;                         2Swift默认支持继承;                         3Kotlin使用contructor定义构造函数,且分为主构造和次构造函数,次构造函数必须调用主构造函数;                          4Kotlin使用this调用其它构造函数; 5Swift使用this调用其它构造函数,但必须添加convenience关键字;                6Swift使用init作为构造函数,deinit作为析构函数;

结构体

不支持

struct关键字                值类型

Swift类和结构体的区别是引用类型、值类型

自增或自减

vara1 = 1
print(a1++)   //输出1
print(++a1)   //输出3

print(a1--)   //删除3
print(--a1)   //输出1


var a = 1

a += 1

a -= 1

1Kotlin支持++—;                               2Swift不支持++—, 但支持+=-+

控制流

 var x = 10

    when(x) {   //不用break关键字

        0, 1 -> {     //使用逗号分隔,当x等于01时执行

            print("第一条语句")

            print("第二条语句")

        }

        2 -> {    //只有1个值时

            print("值等于2")

        }

        in 3..10 -> {  //区间操作符,关键字是in..值为[3,10]

            print("区间操作符")

        } 

        !in 11..20 -> { //值不在[11,20]范围内

            

        } else -> {

            //条件都不符合,默认处理

        }

    }

var a = 100                                                    switch a {

case 0,1:  //多个条件

    print("第一条语句")

    print("第二条语句")

case 2:  //一个条件

    print("值等于2")

case 3...10:  //区间操作符

    print("区间操作符")

case 10...1000 where a%10==0:   //添加where条件判断条件

    print("执行where语句")

default:

    print("默认处理")

}

1Kotlin使用when作为条件判断关键字,不用break关键字;                             2Swift使用switch关键字作为分支判断关键字;

if

vara = 1
var b = 2
val max = if(a>b) {
    print(
"choose a")
    a
}
else {
    print(
"choose b")
    b
}


var a = 1

var b = 2


var max: Int

if a > b {

    max = a

} else {

    max = b

}

KotlinSwiftif语句逻辑一样,区别是Swift if语句不需要括号

非空操作符

vals1 = "this is a string"
val s2: String? =null
val
ret1 = s1 ?:return
val
ret2 = s1 ?:"default value"
val ret3 = s2 ?:"default value"
val ret4 = s1 ?: "default"
print(ret1)   //this is a string
print(ret2)   //default value
print(ret3)   //default value
print(ret4)   //this is a string

Kotlin使用?:作为操作符,如果前面值非空则等于前面的值, 否则取后面的值

let s1 = "this is a string"

let s2: String? = nil

let ret1 = s1 ?? "default"  //this is a string

let ret2 = s2 ?? "default"  //default

1Kotlin使用?:作为操作符取非空值;    2Swift使用??作为操作符取非空值;

标签

标识符后加@ 可以作为代码跳转的地方;语法类似于C语言的goto                                                                       loop@ for (i in 1..100) {

    for (j in 1..100) {

        if (……) break@loop

    }

}

不支持

1Kotlin使用的分支跳转语法;                2、早就被淘汰的语法,影响代码整体逻辑; 不建议使用。

接口

interface关键字

protocol关键字

不用实现函数体

内部类

inner关键字,  内部类访问外部类时持有引用。实例:super@Outer

open class Foo {

    open fun f() { println("Foo.f()") }

    open val x: Int get() = 1  //只读属性

}


class Bar : Foo() {

    override fun f() { /* …… */ }

    override val x: Int get() = 0


    inner class Baz {

        fun g() {

           super@Bar.f() //调用 Foo 实现的 f()

            println(super@Bar.x) //使用 Foo 实现的 x getter

        }

    }

}

class Ext: Basic {

    override func method() {

        print("Ext class method")

    }

    

    //内部类不能访问外部类

    class Baz {

        func  g() {

            

        }

    }

}

1Kotlin内部类持有外部类的引用,但是语法有区别。                                          2Kotlin支持覆盖方法和属性;          3Swift支持覆盖方法,不支持覆盖属性;                                                        4Swift内部类不能访问外部类的方法、属性;                                                    5、都使用override关键字覆盖方法;

单例

Kotlin不支持静态类型,使用伴生对象。 使用私有构造函数并添加同步锁,类不能被继承;                                                             class SingleTon private constructor(str: String){
   
var name: String? =null
    var
age: Int =0
   
var addr: String ="address"

   
init {
        println(
"str is $str")
       
name = str
    }

   
companion object {
       
@Volatile
        private var
instance: SingleTon? =null

        fun
getInstance(c: String): SingleTon {
           
if (instance ==null) {
                synchronized(SingleTon::
class){
                   
if (instance ==null) {
                       
instance = SingleTon(c)
                    }
                }
           
}

           
return instance!!
        }
    }
}


使用static关键字                                                final class SingleTon {  

    //单例类的属性  

    var name: String  

    var age: Int  

      

    private init() {  

        name = ""  

        age = 0  

        print("SingleTon init is called")  

    }  

      

    static let sInstance = SingleTon()  

}  

1、构造函数声明为私有函数,外部类无法实例化;                                                    2Kotlin需要添加同步锁synchronized Swift不需要添加同步锁;                              3Kotlin使用伴生对象声明静态属性, Swift使用static声明静态属性;

权限

private意味着只在这个类内部(包含其所有成员)可见;

protected—— private一样 +在子类中可见。

internal ——能见到类声明的 本模块内的任何客户端都可见其 internal 成员;

public ——能见到类声明的任何客户端都可见其 public 成员。

open   可以其它作用域被访问、继承            public可以访问自己模块中源文件里的任何实体,别人也可以通过引入该模块来访问源文件里的所有实体。

internal可以访问自己模块中源文件里的任何实体,但是别人不能访问该模块中源文件里的实体。

fileprivate文件内私有,只能在当前源文件中使用。

private只能在类中访问,离开了这个类或者结构体的作用域外面就无法访问。            


扩展

扩展方法: fun类名.方法名(参数…):返回值类型 { 函数体 }                //扩展方法

fun String.size(): Int {

    return this.count()

}

var str = "this is a string"

print(str.size())                                                                               扩展属性:valvar类名.属性名类型                                 var String.testNum: Int

       get(): Int {

           return this.count()

       }

       set(value) {

           print("测试")

       }

extension关键字,作用域是整个模块             //仅支持扩展方法,不支持扩展属性

extension String {

    func testMethod() {

        print("extension testMethod")

    }

}

var str = "this is a string"

str.testMethod()

1Kotlin支持扩展属性和方法;                  2Swift支持扩展方法,但不能扩展属性;                                                        3Kotlin不需要关键字, Swift使用extension关键字;

基类

Any所有类的基类

AnyClass

1Kotlin使用Any作为基类,类似于JavaObject                                    2SwiftAnyAnyObjectAnyClass所有类的基类是AnyClass3、泛型和基类派生类引用会用到。

数据类

data class User(var id: Int, var name: String)

 var user: User = User(1, "zhangsan")   //实例化

 var (id, name) = user //取值

 user.name = "lisi"

 print("${user.component1()} ${user.component2()}")   //1 lisi

 print(" ${user.id} ${user.name}")      //1 lisi

不支持

1Kotlin使用data class关键字声明数据类,即类只有属性,不需要实现自定义函数;                                                          2Swiftclass实现数据类;

泛型

classBox<T>(t:T) {
   
var value= t
}

varobj = Box(1)                   fun <T> chkType(content:T) {
   
if(content is Int) {
        print(
"整型")
    }
else if (contentis Float) {
        print(
"浮点型")
    }
else {
       
    }
}

class A<T> {

    var value: T

    init(param: T) {

        value = param

    }

}

var obj = A(param: 1)

print(obj.value)  //输出1                                           func testType<T>(content: T) {

    if content is Int {

        print("整型")

    } else if content is Float {

        print("浮点型")

    } else {

        

    }

}

KotlinSwift的泛型声明方式类似,都是<T>格式,泛型也可以继承于某类例如<T: String>

枚举

enum classDirection {
   
NORTH, SOURTH,WEST, EAST
}

varenum1 = Direction.EAST

enum Orientation: Int {

    case NORTH = 0

    case SOURTH

    case WEST

    case EAST

}


var value: Orientation = .EAST

print(value.rawValue)   //输出3

1Kotlin声明枚举的语法跟Java类似;     2Swift声明枚举的每个值都带前缀case;

接口

interface Base {

    fun print()

}


class BaseImpl(val x: Int) : Base {

    override fun print() { print(x) }

}

protocol Base {

    func testMethod()

}


class BaseImple: Base {

    var age: Int?

    init(x: Int) {

        age = x

    }

    

    func testMethod() {

         print(" testMethod \(age)")

    }

}

var obj = BaseImple(x: 10)

obj.testMethod()

1Kotlin使用interface关键字声明接口; 2Swift使用protocol关键字声明接口;  3、冒号实现一个或若干个接口;

类型转换

is  as  !is as?关键字

is as as? as!

类型转换关键字,用法类似; 区别是as!可能抛异常。

相等性

3个等号和2个等号

3个等号和2个等号

1 ===表示地址相同;   2==表示值相等,即equals方法为真;

注解

在类名、函数名同行添加注解                                             实例:class Tests {

    // @Rule 注解应用于属性 getter

    @get:Rule val tempFolder = TemporaryFolder()


    @Test fun simple() {

        val f = tempFolder.newFile()

        assertEquals(42, getTheAnswer())

    }

}

一般不使用           例如app的入口类是@UIApplicationMain

1Kotlin的注解方法有点特别,是在当前行添加;                                                            2Swift很少使用注解;


2017-06-23 16:39:25 Xoxo_x 阅读数 997
  • 为什么Kotlin是你下一个要掌握的语言?

    Kotlin教程:Kotlin是一门与Swift类似的静态类型JVM语言,由JetBrains设计开发并开源。与Java相比,Kotlin的语法更简洁、更具表达性,而且提供了更多的特性,比如,高阶函数、操作符重载、字符串模板。它与Java高度可互操作,可以同时用在一个项目中。本课程结合讲师的实践案例为同学们深度讲解Java转kotlin需要知道的一些事。

    5568 人正在学习 去看看 CSDN讲师

一位国外的程序员认为 Swift 的语法与 Kotlin 相似,并整理了一些 Swift 和 Kotlin 的对比,下面是一些例子,大家不妨也看看。

http://www.oschina.net/news/85013/swift-is-like-kotlin

2016-10-21 17:27:26 Bevin_Chan 阅读数 2519
  • 为什么Kotlin是你下一个要掌握的语言?

    Kotlin教程:Kotlin是一门与Swift类似的静态类型JVM语言,由JetBrains设计开发并开源。与Java相比,Kotlin的语法更简洁、更具表达性,而且提供了更多的特性,比如,高阶函数、操作符重载、字符串模板。它与Java高度可互操作,可以同时用在一个项目中。本课程结合讲师的实践案例为同学们深度讲解Java转kotlin需要知道的一些事。

    5568 人正在学习 去看看 CSDN讲师

为什么我们要学Kotlin语言:

  • 它是IntelliJ的公司jetBrains出色团队开发的一门JVM语言,无缝对接Java混合编程,如果说Scala是Android的c++,那么Kotlin就是Android的swift语言
  • 只需安装插件和配置gradle环境,就可以在Android Studio上流畅开发
  • 它时null安全的,让你减少很多调试空指针的时间
  • *它具有互操作性,可以引用Java库,类方法,而且兼容主流第三方框架,例如RxJava,Retrofit等
  • 它的代码更简洁,操作符更强大
  • 它可以扩展函数

没时间解释了,快上车吧,开始我们的Kotlin之旅

每次配置环境都屎那么的香菇,蓝瘦

gradle配置,可先配置上anko库,例如:

apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'

dependencies {
    compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
    compile "org.jetbrains.anko:anko-sdk15:$anko_version"
    compile "org.jetbrains.anko:anko-support-v4:$anko_version"
    compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
    compile 'com.android.support:design:24.2.1'
}

既然配置了plugin,那么classpath也要配置一下:

buildscript {
    ext.anko_version = '0.8.2'
    ext.kotlin_version = '1.0.4'
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.2.1'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        classpath "org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version"

    }
}

注意:配置好环境了,那么请尽量把Android Studio的版本升到2.2及以上,并安装plugin: File > Settings > Plugin >搜索“Kotlin”
安装插件的时候耐心点,可能网络的原因,需要多次确定才能继续下载,一边撩妹一边安装,两边不能方。
使尽洪荒之力安装好了,我已经很满意了,那就开始我们的开发之旅了,记住,目前只支持单向转换,每次只能转换一个class到kt,要是怕刚入手不小心搞黄项目的,可以先在新的project里练手,快捷键:crol+shift+alt+k

类与函数的刀剑如梦

相信写惯了java的筒子们一看到Kotlin代码有点似曾相识的感觉,其实就相当于java语言的扩展,毕竟java属于后端语言,而kotlin更适合我们安卓前端的开发

如何定义一个类,用class关键字即可

class MainActivity{
}

而Kotlin的类,有一个默认构造函数,只需要在类名后面加上我们的参数:

class MainActivity(val name: String,val id :Int){
   init{
     ...
   }
}

如果类中没有内容的话可以省略大括号,而构造函数的函数体,可以写在init块中,咦,怎么基本类型跑到冒号后面呢,后面会提到。那我们需要继承一个类及实现view呢,看下面:

class MainActivity():AppCompatActivity(),CommonView{
}

接下来看我们Kotlin的函数(相当于java中的方法),只需要加上fun关键字即可,而覆写类会在fun前加上override

fun loadImage(){
}

如果函数需要返回类型:

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

在Kotlin中分号;不是必须的,也不会报错,少写了分号是不是感觉很斯国一,减少了Androud编程中最多的符号。如果上面的函数可以用一条表达式完成的话,就可以简化大括号了

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

之前我们注意到参数的写法和我们java的不太一样,基本类型写到冒号后面了,这就是Kotlin的设计特点,它的世界全是对象,因此我们是先写参数再写类型
同时我们可以了解一个Kotlin类型很强大的特点, 例如String类型:

"My name is ${user.name}"

假如我们有一个变量,而$符号就可以在字符串里插入表达式,这样是不是比我们的java显得阔以啊?

类与函数就是我们程序员的刀剑,代码风格的简化可以给我们减少大量的代码冗余,所谓磨刀不误砍柴工,入门新语言的时候,希望能耐心的对待每一个脚步的学习积累。
新入手的筒子们可以观摩Kotlin的一门入门书籍练手基础,基本的知识就不多做解释了http://github.com/wangjiegulu/kotlin-for-android-developers-zh/blob/master/SUMMARY.mdKotlin小乐园QQ群:479109923

Kotlin的变形金刚-anko库

之前 已经添加了anko库的plugin和依赖,已经可以直接使用了,anko是用Kotlin语言编写的支持库, 但是我们目前还不能使用太多anko里面的内容,他能帮我们简化代码布局,实例化Intent,Activity之间的跳转等等,在以后的学习中,希望能穿插进去

首先我们来看看如何简化Activity的跳转,我们需要从MainActivity,跳转到DetailActivity,并需要Intent传递两个参数,用anko库提供了reified函数如下:

DetailActyivity.class:

companion object {
        val ID = "DetailActivity:id"
        val CITY_NAME = "DetailActivity:cityName"
    }

companion object相当于我们java中的静态static,但与java不同的是它会实例化对象,而里面的对象会随类生,随类似,也就是我们的伴生
而val是不可变变量(具体参考上面链接书籍),相当于java的public static final ,Kotlin中建议变量一般使用val,因为不可变显得更加可控。

再看看MainActivity.class中的代码

startActivity<DetailActivity>(DetailActivity.ID to it.id,
                        DetailActivity.CITY_NAME to result.city)

假如我们网络请求后得到一个POJO类(JavaBean)result
此时我们跳转Activity时只需将id和city字段返回结果传参过去,就替代了Intent的实例化,这就是Activity跳转的anko代码
但是我们有疑问的是it哪来的?没错他就是Kotlin的亲儿子,能力相当于java的this,但又比java更强大,可以代替指定对象,但是在传参是它只能代替一个对象,相当于左边的参数,也就是result。

见识过anko库第一个用法之后,接下来再看我们使用最多的findViewById

 <Button
     android:id="@+id/bu_toast"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"/>

而在anko库中已经封装好了

val button by lazy{find<Button>(R.id.button)} 

我们来剖析他,首先find<>里面是控件的类型,()内是id的名字,这样就完成了一次fvb,那么by lazy是什么鬼?它相当于java中的懒加载,在有些变量我们想在我们使用的时候再初始化,这时他就派上用场了,比java考虑的周全吧,节省了内存。它只能用在不可变变量val,因此是线程安全的。
anko库我就不想说太多了,毕竟也是用Kotlin语言写得,在代码布局方面也有一定的优越性,而我用的更多的是它的其他功能,以后会穿插的介绍。毕竟上个月谷歌刚推出了约束布局ConstraintLayout的正式版,又多了一样装逼的技能。

告别fvb的时代

上一节我们说到了如何用anko库实现fvb,就是一白痴化操作,下面更神奇的地方来了,还记得我们添加了一个extensions的plugins吗,奇了怪了,这是啥用的,简单来说,它就是为了节省fvb而生的的。写了这么多的java代码,是不是感觉到怀疑人生,一部分的时间都用来findviewbyid,即使有了黄油刀注解还有fvb的插件,但还是觉得很占地方。此时它就是你的救世主了,只需要手动导入以下import头

 import kotlinx.android.synthetic.main.activity_main.* 

其实只要你加载layout然后输入控件id的时候,它就自动导入了
下面我们来实现简单的效果,我想让一个 TextView去设置文字:

 <TextView
     android:id="@+id/tx_view"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"/>
tx_view.text("helloKotlin")

这样一句就完成了?不可思议,相信你的钛合金眼没看错,就是so easy,fvb找控件也省了, setText也之间简化成.text,这也是Kotlin的亮点之一。
当然,有亮点肯定有痛点,如果不同布局两个id命名相同冲突的话就有点恶心了,所以用惯了mvp模式的筒子们不如尝试下用dataBinding,毕竟是谷歌爸比推出的东西,而且实现了双向绑定,同样可以使用Kotlin的.text,这何尝不是一件快事呢。

https://github.com/YeungKC/Gank.io-for-Kotlin-Android

Kotlin项目实战的初尝禁果

在这里我不想像其他博主那么将一个demo硬生生的拉进来,毕竟开发这种东西随机应变,只要掌握了方法就是造轮子。
至于github上的demo也不少,大可自己去搜索,不要道德绑架别人给你写你要的demo,先掌握好你的基础,再去慢慢实战,例如github.com/YeungKC/Gank.io-for-Kotlin-Android

回到正题,相信大家都开始用上了RecyclerView了吧,亮点自然不少,最亮的还是自定义LayoutManager, 痛点呢最常见的当然是没有时间点击还有上拉加载,在这里我跟大家讲讲如何在Kotlin写RecyclerView的条目事件点击。一群水军又沸腾起来了,说了那么多不就是写接口嘛,还能怎样,错了,虽然Kotlin里也有interface,但是无需用到它。

第一步:声明一个回调监听器

var onItemCheckedListener: ((day: Day) -> Unit)? = null

为什么有Lambda表达式?因为内置了。不想用?要想马儿跑,又要马儿不吃草,大概是这种道理,因为java8的到来,函数式使安卓编程变得更加简洁,别怕,两句话你就能看懂这条表达式,箭头左边是参数,右边是代码块,至于Unit是Kotlin的关键字意思是无返回值。如果没有参数,箭头左边可以是(),或者可以直接省略左边还有箭头,这就是lambda表达式,还不懂,找度娘去温柔乡一下。

第二步,执行回调函数

 class Holder(val root: View) : RecyclerView.ViewHolder(root) {
        var onCheckListener: ((i: Int) -> Unit)? = null

        init {
            root.onClick {
                onCheckListener?.invoke(adapterPosition)
            }
        }
    }

onCheckListener是个 局部声明,在选中的时候会调用Kotlin的invoke()方法,至于括号内的adapterPosition直接调用的是RecyclerView的getAdapterPosition(),源码如下:

 public final int getAdapterPosition() {
            if (mOwnerRecyclerView == null) {
                return NO_POSITION;
            }
            return mOwnerRecyclerView.getAdapterPositionFor(this);
        }

第三步:RecyclerView创建监听绑定

override fun onCreateViewHolder(p0: ViewGroup?, p1: Int): Holder? {
        val holder = Holder(LayoutInflater.from(context).inflate(R.layout.***, p0, false))
        holder.onCheckListener = {
            onItemCheckedListener?.invoke(dates!![it])
        }
        return holder
    }

此时it代替应该是adapterPosition,在kotlin中,当传参时只有一个参数时,可以代替,而不用写左边的参数。而onItemCheckedListener这个全局声明就是我们Item点击 监听,此时holder.onCheckListener是为了在RecyclerView创建时调用
onItemCheckedListener?.invoke(dates!![it]),刚接触可能有点懵逼,多练手下应该能看懂此处设计的巧妙之处,而大家可能最懵逼的还是这个invoke()方法,在我的理解中调用他就相当于java中的接口,当view持有监听的时候就会回调到invoke方法,而invoke()方法括号里的参数取决于声明时的参数,这时回看第一步,是不是恍然大悟,lambda表达式的入参在这里被调用了。

第四步:View持有的条目点击监听

adapter.onItemCheckedListener = {
          ...
 }

此时实例化RecyclerView的adapter,大括号内就是点击时的界面操作了巧妙之处就是大括号内可以持有第三步invoke(dates!![it])括号内的引用。

看完这几步,是不是感觉天生懵逼难自弃,没关系,慢慢来。

下面又引发疑问了,dates哪来的,为什么后面有!!,先说这个!!吧,就是Kotlin中非空的意思。
接下来看dates:

var dates: Array<Day>? = null
        set(value) {
            field = value
            if (currSelect == null && value != null) {
                currSelect = value[0]
                lastPosition = 0
            }
            notifyDataSetChanged()
        }

这个嘛,不是个神奇的东西,就是我们java中常见的setter,因为Kotlin的变量本身就默认有getter和setter,能给编程少了很多冗杂的代码,但是这里是对setter的覆写,当我们发现我们要重新设置数据源的时候,它就得出现了。
来看看RecyclerView的构造:

class DateAdapter(context: Context, dates: Array<Day>? = null) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {

上面我们说过类的构造函数默认在()里面,当我们new这个类的时候,就将数据源传进来,当需要重新设置数据源的时候,set()覆写就派上用场了。
现在明白onItemCheckedListener?.invoke(dates[it])里的dates[it]其实就是回调选中的dates[adapterPosition]数据。上面的代码参照demohttps://github.com/zzhoujay/DailyGank

好了,但是还是不太满意上面的写法,那我们尝试在简化一下它:

class DateAdapter(context: Context, dates: Day,val itemClick: (Day) -> Unit) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {

上面我们说到构造已经将数据源dates传进来了,这次我们的数据源直接以domain的方式传进来,我们增加了一个对象itemClick,如果我们在这里将它配置了,那么传构造的时候就不需要这个参数了,这是Kotlin的一个好处,那我们再改一下初始化的代码:

 val holder = Holder(LayoutInflater.from(context).inflate(R.layout.***, p0, false),itemClick)

绑定布局的代码也修改一下:

 override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.bindForecast(dates[position])
    }

这里我们往Holder传了入参itemClick,再看看Holder的代码怎么改:

 class Holder(val root: View,val itemClick: (Day) -> Unit) : RecyclerView.ViewHolder(root) {
        fun bindForecast(day: Day) {
        with(day){
            itemView.setOnClickListener{
                //itemClick.invoke(this)
                //在这里我们可以直接省略invoke方法,这是Kotlin的设计
                itemClick(this)
            }
        }
    }

这里的this指的就是day,而with是Kotlin函数扩展中重要的一个操作符,如果没有with,Kotlin无法辨别大括号里的数据源是day,也就是我们无法使用绑定的数据源。这个with接收一个T类型的对象还有一个扩展函数,因为函数可以放在()外,也就是{}里的内容,而this可以访问这个函数代码块里所以public的方法和属性,这也是Kotlin需要关注的重点知识之一。

我们有一个请求回来的数据源result,想到点击弹出一个吐司去展示日期:

val adapter = DateAdapter(this,result){toast(it.data)}

咦,这个吐司?没看错,Kotlin的吐司就是这么简单,一个toast()搞定。
此时你是不是觉得用上lambda表达式简单了很多,省略了接口写法。

这里我们一鼓作气就完成了两种事件点击的方案,厉害了我的哥。

刚才讲到了空安全,就不得不提一下这个?了,为什么要在对象后面加上问号呢,表示如果该对象为空时什么都不做,不为空则执行后面的函数。这节省了我们很多调试空指针的时间,何乐而不为。
我们可能会遇到这种情景,我们确定我们是在用一个非null变量,但是他的类型却是可null的。我们可以使用!!操作符来强制编译器执行可null类型时跳过限制检查。

POJO类的爱恨情仇

讲到Kotlin的优点,不得不赞的就是数据类了。虽然现在有gsonformat,但是公司操蛋的后台并不会给你那么规范,有的字段就不给你,有的就给你个null,在解析的时候不得不手写纠正。有了Kotlin,写JavaBean就是一件变得方便的事。

data class User(username:String,id:Int)

一个JavaBean搞定了,啊?这么简单,就是这么简单,除了序列化之类,所以的getter,setter,toString,hashCode已经给你生成了,构造也有了,直接用就行了。
那我要序列化呢,还有Gson将命名对应字段名呢,别方,看下面:

data class Gank(@SerializedName("username")
                var UserName: String,
                @SerializedName("id")
                var UserId: Int,
                @SerializedName("createdAt")
                var createdTime: Date,
              ) : Serializable, Parcelable {
    constructor(source: Parcel) : this(source.readString(), source.readString(), source.readSerializable() as Date))

    override fun describeContents(): Int {
        return 0
    }

    override fun describeContents(): Int {
        return 0
    }

    constructor() : this("", "", Date())

    override fun writeToParcel(dest: Parcel?, flags: Int) {
        dest?.writeString(UserName)
        dest?.writeString(UserId)
        dest?.writeSerializable(createdTime)
    }

    companion object {
        @JvmField  val CREATOR: Parcelable.Creator<Gank> = object : Parcelable.Creator<Gank> {
            override fun createFromParcel(source: Parcel): Gank {
                return Gank(source)
            }

            override fun newArray(size: Int): Array<Gank?> {
                return arrayOfNulls(size)
            }
        }
    }
}

搞定,序列化完成,使用@SerializedName注解字段别忘了添加gson包

头盘菜的压轴甜品

说到这里,必须要给你看看Kotlin是怎么面对疾风吧,我觉得这也是用Kotlin最爽的一个地方了,那就是扩展函数:

新建一个Kotlin file作为我们的扩展类,直接把下面的函数丢进去就行了
fun ImageView.loadImg(imageUrl: String) {
    if (TextUtils.isEmpty(imageUrl)) {
        Glide.with(context).load(R.mipmap.ic_launcher).into(this)
    } else {
        Glide.with(context).load(imageUrl).into(this)
    }
}

接下来神奇的事情发生了,假如我们的RecyclerView Item布局里有一个ImageView控件,id是mImageView,接下来我们要给它设置图片,我们用现在主流的Glide图片框架:

mImageView.loadImg(**)

**处填图片的路径,就这样完成了图片加载,不是吧?加载类我是写在扩展类的,而且连扩展类都没有导入,放心,Kotlin已经帮你完成了,只要任何类的控件属于ImageView类型,都可以无障碍使用这个扩展函数,太爽了吧,比单例还爽。

public这个老司机

再爽一下下,Android开发中写得最多的是什么,那可能访问权限能排上号,Kotlin的var是可变变量,val是不可变变量,它们都默认是public的,在java中这个域是公共的,但是在Kotlin是否一样呢?
不是的,有兴趣的小伙伴可以反编译apk来看看其实Kotlin中的public就等于private+getter+setter,是不是震精了。

还没爽完,这篇就暂时写这么多了,后面有待填坑,Kotlin语言的宗旨就在于让java开发者更快的适应,虽然比Scala简单,但是也要考验你的java编程水平。
喝口水平静下我呆萌的心灵,然后广告插播博客,欢迎Kotlin爱好者加入交流群 Kotlin小乐园QQ群:479109923
非爱好者勿入,问安卓基础者勿入,谢谢。

2015-12-02 23:47:53 u012464435 阅读数 537
  • 为什么Kotlin是你下一个要掌握的语言?

    Kotlin教程:Kotlin是一门与Swift类似的静态类型JVM语言,由JetBrains设计开发并开源。与Java相比,Kotlin的语法更简洁、更具表达性,而且提供了更多的特性,比如,高阶函数、操作符重载、字符串模板。它与Java高度可互操作,可以同时用在一个项目中。本课程结合讲师的实践案例为同学们深度讲解Java转kotlin需要知道的一些事。

    5568 人正在学习 去看看 CSDN讲师

Kotlin-Android的Swift

Kotlin介绍

最近在学习一门新的语言Kotlin, Google拟用Kotlin取代Java进行Android开发。众所周知,苹果用swift取代Objective-C进行Swift开发,Kotlin对于Android就好比swfit对于iOS一样。不过,Kotlin对于Android开发的影响,所带来的优势可能比swift对iOS更大。
尽管还有基于JVM的语言Scale和Groovy可供选择,但是用它们进行Android开发代价比较大,因为这两门语言包的大小以及方法的数量都容易超出App的限制,尤其是在没分包情况下,一个应用的方法数量不能超过65536;所以为了用一门更好的语言进行Android开发,综合考虑,Kotlin是最佳的选择。
Kotlin是一门基于JVM的语言,这也意味着能够兼容Java。Kotlin是由大名鼎鼎的JetBrains发明的,这家公司是许多顶尖IDE工具的发明者,包括IntelliJ IDEA(就是Android Studio他妈)

用Kotlin进行Android开发

  1. 直接使用XML布局文件
class KotlinActivity : ActionBarActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_kotlin)
    }

    override fun onCreateOptionsMenu(menu: Menu):Boolean {
        menuInflater.inflate(R.menu.menu_main, menu)
        return true
    }
}
  1. 代码中定义布局,动态加载控件
  2. DSL

kotlin

阅读数 87

没有更多推荐了,返回首页