Kotlin中文文档

Kotlin中文文档

Kotlin中文文档
在线调试

在线调试

Kotlin在线调试工具
开发工具

开发工具

Kotlin开发工具IntelliJ IDEA
技术问答

技术问答

Kotlin技术问答与交流专区

【译】Java、Kotlin、RN、Flutter 开发出来的 App 大小,你了解过吗?


现在开发 App 的方式非常多,原生、ReactNative、Flutter 都是不错的选择。那你有没有关注过,使用不同的方式,编译生成的 Apk ,大小是否会有什么影响呢?本文就以一个最简单的 Hello World App,来看看不同的框架,编译出来的 Apk 大小,有什么区别。当然,本文的环境下是一个最简单的 Apk,其实只能部分说明问题,你觉得呢?
— 承香墨影

移动开发发展至今,已经可以接受很多方式来开发 App,例如基于特定平台的原生开发方式(使用 Java 或者 Kotlin 开发 Android,使用 Objective-C 或者 Swift 开发 iOS);基于 Facebook 提供的 ReactNative;基于 Walmart 的 Electrode Native;基于 Ionic 框架;使用 Unity 开发一些特定的 App,以及最近 Google 发布的 Flutter.io 框架来开发 App。

那你有没有思考过,这些库和框架,是否会对你的 App 大小有所影响?

我们来分别分析以这些方式编写的应用程序的 Apk 文件,这些应用程序非常的简单,只包含顶部的标题和屏幕中心的文本控件(Hello World)。这是一个最低限度的基本 App。

首先对于这个测试,我会创建四个不同版本的 Apk。分别是:Java、Kotlin、React Native 和 Flutter。Android Api Level 均为 27。

然后使用 Android Studio 编译成 Release 包,使用对应的 cli 编译 React Native 和 Flutter。

它们将使用默认的 proguard 配置,最后我们使用 Android Studio 自带的 Analyze APK 分析这些 Apk。

Java(539 KB)

首先使用 Java 来开始这次实验,使用 Java 开发 Android 算是最常规也是最简单的一种方式。正如前面描述的那样,由于我们仅仅使用了 Java 和 Android 框架来创建这个应用程序,所以它将是最小的,唯一的依赖是 Android 支持库,在这里你可以看到它占用了整个 Apk 内相当多的空间。

我们可以通过删除一些依赖库,使用 Activity 而不是 AppCompatActivity 来进一步降低应用程序的大小。

Kotlin(550KB)

接下来,我们使用 Kotlin。如果你使用 Java 编写过很长一段时间的代码,我想 Kotlin 应该会让你眼前一亮。Kotlin 应用程序的 Release 版本,包含了我们在 Java APK 中能看到的所有内容,以及一些基于 Kotlin 的语法糖信息。

React Native(7MB)

如果你有前端(Web)的开发经验,并希望使用 JavaScript 来开发 App,那么 React Native 是一个不错的选择。

如果你希望在已发布的 App 上,进行更快的功能迭代,使用 React Native 也可以让你不必为每个小改动都发布应用市场。

由 React Native 生成的 Release apk 在 classes.dex 文件中有几个类,这些类有 12193 个针对此应用程序的引用方法。

它还在 x86 和 armeabi-v7a 的 lib 目录中添加了一些 so 库。总共添加了大约 6.4 MB 的空间。

Flutter(7.5MB)

由 Flutter 的 cli 生成的 Release 版本的应用程序中,包含 C / C ++ 引擎和 Dart VM,它们构成了 Apk 的几乎所有部分。该应用程序直接使用本机指令集运行,不涉及任何解释器。

本文里介绍的几种编写 App 的方法,都存在优缺点,在实际工作中,应该根据需求选择适合的方式。你还可以混合搭配这些框架,仅仅用它们的优点来开发 App 的部分功能。

例如,如果你想在 iOS 和 Android 应用程序之间共享代码,你可以尝试使用 React Native 创建某些组件,具体操作请查看 React Native 或 Flutter.io 的官方文档,如果你只关注 Android ,并且 Apk 大小是你一个比较重要的指标,你可以使用 Java 或 Kotlin。

本文的数据,其实都是基于一个最简单的 APK,如果是分析 APK 大小的话,其实还有一个很重要的指标没有参考,就是代码量的递增,对 APK 大小的影响。

ReactNative 和 Flutter 因为其内部还需要包含一些解析器和引擎,本身就会有一些基础库在其内,所以变大也是符合预期的。

举个例子:不同城市出租车的起步价不一样,有些城市可能是 14 元起步,有些则是 7 元起步价,但是可能 14 元起步价的后期每公里递增的价钱比 7 元起步价的低。这样在两个城市,开到多少公里之后,总是会有一个平均值,让它们的费用相等。

在这些框架中也是一样,它们只是起步价不一样而已。
 
 
原文链接: https://android.jlelse.eu/comparing-apk-sizes-a0eb37bb36f
http://www.jcodecraeer.com/a/anzhuokaifa/2018/0327/9526.html
继续阅读 »

现在开发 App 的方式非常多,原生、ReactNative、Flutter 都是不错的选择。那你有没有关注过,使用不同的方式,编译生成的 Apk ,大小是否会有什么影响呢?本文就以一个最简单的 Hello World App,来看看不同的框架,编译出来的 Apk 大小,有什么区别。当然,本文的环境下是一个最简单的 Apk,其实只能部分说明问题,你觉得呢?
— 承香墨影

移动开发发展至今,已经可以接受很多方式来开发 App,例如基于特定平台的原生开发方式(使用 Java 或者 Kotlin 开发 Android,使用 Objective-C 或者 Swift 开发 iOS);基于 Facebook 提供的 ReactNative;基于 Walmart 的 Electrode Native;基于 Ionic 框架;使用 Unity 开发一些特定的 App,以及最近 Google 发布的 Flutter.io 框架来开发 App。

那你有没有思考过,这些库和框架,是否会对你的 App 大小有所影响?

我们来分别分析以这些方式编写的应用程序的 Apk 文件,这些应用程序非常的简单,只包含顶部的标题和屏幕中心的文本控件(Hello World)。这是一个最低限度的基本 App。

首先对于这个测试,我会创建四个不同版本的 Apk。分别是:Java、Kotlin、React Native 和 Flutter。Android Api Level 均为 27。

然后使用 Android Studio 编译成 Release 包,使用对应的 cli 编译 React Native 和 Flutter。

它们将使用默认的 proguard 配置,最后我们使用 Android Studio 自带的 Analyze APK 分析这些 Apk。

Java(539 KB)

首先使用 Java 来开始这次实验,使用 Java 开发 Android 算是最常规也是最简单的一种方式。正如前面描述的那样,由于我们仅仅使用了 Java 和 Android 框架来创建这个应用程序,所以它将是最小的,唯一的依赖是 Android 支持库,在这里你可以看到它占用了整个 Apk 内相当多的空间。

我们可以通过删除一些依赖库,使用 Activity 而不是 AppCompatActivity 来进一步降低应用程序的大小。

Kotlin(550KB)

接下来,我们使用 Kotlin。如果你使用 Java 编写过很长一段时间的代码,我想 Kotlin 应该会让你眼前一亮。Kotlin 应用程序的 Release 版本,包含了我们在 Java APK 中能看到的所有内容,以及一些基于 Kotlin 的语法糖信息。

React Native(7MB)

如果你有前端(Web)的开发经验,并希望使用 JavaScript 来开发 App,那么 React Native 是一个不错的选择。

如果你希望在已发布的 App 上,进行更快的功能迭代,使用 React Native 也可以让你不必为每个小改动都发布应用市场。

由 React Native 生成的 Release apk 在 classes.dex 文件中有几个类,这些类有 12193 个针对此应用程序的引用方法。

它还在 x86 和 armeabi-v7a 的 lib 目录中添加了一些 so 库。总共添加了大约 6.4 MB 的空间。

Flutter(7.5MB)

由 Flutter 的 cli 生成的 Release 版本的应用程序中,包含 C / C ++ 引擎和 Dart VM,它们构成了 Apk 的几乎所有部分。该应用程序直接使用本机指令集运行,不涉及任何解释器。

本文里介绍的几种编写 App 的方法,都存在优缺点,在实际工作中,应该根据需求选择适合的方式。你还可以混合搭配这些框架,仅仅用它们的优点来开发 App 的部分功能。

例如,如果你想在 iOS 和 Android 应用程序之间共享代码,你可以尝试使用 React Native 创建某些组件,具体操作请查看 React Native 或 Flutter.io 的官方文档,如果你只关注 Android ,并且 Apk 大小是你一个比较重要的指标,你可以使用 Java 或 Kotlin。

本文的数据,其实都是基于一个最简单的 APK,如果是分析 APK 大小的话,其实还有一个很重要的指标没有参考,就是代码量的递增,对 APK 大小的影响。

ReactNative 和 Flutter 因为其内部还需要包含一些解析器和引擎,本身就会有一些基础库在其内,所以变大也是符合预期的。

举个例子:不同城市出租车的起步价不一样,有些城市可能是 14 元起步,有些则是 7 元起步价,但是可能 14 元起步价的后期每公里递增的价钱比 7 元起步价的低。这样在两个城市,开到多少公里之后,总是会有一个平均值,让它们的费用相等。

在这些框架中也是一样,它们只是起步价不一样而已。
 
 
原文链接: https://android.jlelse.eu/comparing-apk-sizes-a0eb37bb36f
http://www.jcodecraeer.com/a/anzhuokaifa/2018/0327/9526.html 收起阅读 »

Kotlin+SpringBoot服务端restful框架搭建(3)简单集成swagger2

添加依赖

在之前的的项目添加这些swagger2依赖的类
 
   <dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.8.0</version>
</dependency>
注意:本文只是简单的做集成,目前尝试可以正常启动显示接口信息,但是对于部分嵌套的注解添加会报错,目前还没找到解决方案。 @APiresponses()和@ApiImplicitParams()使用时回报错。
 
添加swagger2配置类

这个配置springboot中使用swagger2类似
package com.kotliner.demo
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import springfox.documentation.builders.ApiInfoBuilder
import springfox.documentation.builders.PathSelectors
import springfox.documentation.builders.RequestHandlerSelectors
import springfox.documentation.service.ApiInfo
import springfox.documentation.spi.DocumentationType
import springfox.documentation.spring.web.plugins.Docket
import springfox.documentation.swagger2.annotations.EnableSwagger2

@Configuration
@EnableSwagger2
class Swagger{


@Bean
fun createRestApi():Docket{
var docket = Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.groupName("业务系统API接口文档")
.select()
.apis(RequestHandlerSelectors.basePackage("com.kotliner.demo"))
.paths(PathSelectors.any())
.build();
return docket;
}

fun apiInfo():ApiInfo{

var api = ApiInfoBuilder()
.title("业务系统名称")
.description("swagger2构建框架restfull API文档")
.contact("猫")
.version("1.0")
.termsOfServiceUrl("")
.build();
return api;

}


}

conroller添加swagger2注解
 
目前只使用了@Api,@ApiOperation,@ApiPara,添加完成后我们就可以启动了。
 
package com.kotliner.demo.controller

import com.kotliner.demo.entity.CaOrder
import com.kotliner.demo.mapper.OrderMapper
import com.kotliner.demo.service.ICaOrderService
import io.swagger.annotations.*
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.web.bind.annotation.*

@Api(value = "order",description = "订单业务")
@RestController
class OrderController{

@Autowired
lateinit var service: ICaOrderService;
@Autowired
lateinit var mapper: OrderMapper


@ApiOperation(value = "订单查询",notes = "订单列表查询")
@RequestMapping(value = "/findAllOrder",method = arrayOf(RequestMethod.POST))
fun findAllOrder(@ApiParam(name="order",value = "订单",required = true) @RequestBody order: CaOrder):List<CaOrder>{
return service.findAllOrder(order);
}

@ApiOperation(value = "订单查询",notes = "订单列表查询")
@RequestMapping(value = "/find",method = arrayOf(RequestMethod.POST))
fun find(@ApiParam(name="order",value = "订单",required = true) @RequestBody order: CaOrder):String{
var orders: List<CaOrder> = mapper.findOrderList(order);


return "ssssssssssss"+orders.toString();
}

@ApiOperation(value = "新增订单",notes = "新增订单")
@RequestMapping(value = "/save",method = arrayOf(RequestMethod.POST))
fun save(@ApiParam(name="order",value = "订单",required = true) @RequestBody order: CaOrder):Int{
return service.saveOrder(order);
}

@ApiOperation(value = "修改订单",notes = "修改订单")
@RequestMapping(value = "/update",method = arrayOf(RequestMethod.POST))
fun update(@ApiParam(name="order",value = "订单",required = true) @RequestBody order: CaOrder):Int{
return service.updateOrder(order);
}


@ApiOperation(value = "根据id删除订单",notes = "根据id删除订单")
@RequestMapping(value = "/delete",method = arrayOf(RequestMethod.GET))
fun delete(@ApiParam(name="id",value = "订单id",required = true) @RequestParam(value = "id") id:Int){
service.deleteOrder(id);
}
}
访问

输入http://localhost:8090/demo/swagger-ui.html地址就可以看到了,新版本的swagger界面做了改版。
继续阅读 »
添加依赖

在之前的的项目添加这些swagger2依赖的类
 
   <dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.8.0</version>
</dependency>
注意:本文只是简单的做集成,目前尝试可以正常启动显示接口信息,但是对于部分嵌套的注解添加会报错,目前还没找到解决方案。 @APiresponses()和@ApiImplicitParams()使用时回报错。
 
添加swagger2配置类

这个配置springboot中使用swagger2类似
package com.kotliner.demo
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import springfox.documentation.builders.ApiInfoBuilder
import springfox.documentation.builders.PathSelectors
import springfox.documentation.builders.RequestHandlerSelectors
import springfox.documentation.service.ApiInfo
import springfox.documentation.spi.DocumentationType
import springfox.documentation.spring.web.plugins.Docket
import springfox.documentation.swagger2.annotations.EnableSwagger2

@Configuration
@EnableSwagger2
class Swagger{


@Bean
fun createRestApi():Docket{
var docket = Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.groupName("业务系统API接口文档")
.select()
.apis(RequestHandlerSelectors.basePackage("com.kotliner.demo"))
.paths(PathSelectors.any())
.build();
return docket;
}

fun apiInfo():ApiInfo{

var api = ApiInfoBuilder()
.title("业务系统名称")
.description("swagger2构建框架restfull API文档")
.contact("猫")
.version("1.0")
.termsOfServiceUrl("")
.build();
return api;

}


}

conroller添加swagger2注解
 
目前只使用了@Api,@ApiOperation,@ApiPara,添加完成后我们就可以启动了。
 
package com.kotliner.demo.controller

import com.kotliner.demo.entity.CaOrder
import com.kotliner.demo.mapper.OrderMapper
import com.kotliner.demo.service.ICaOrderService
import io.swagger.annotations.*
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.web.bind.annotation.*

@Api(value = "order",description = "订单业务")
@RestController
class OrderController{

@Autowired
lateinit var service: ICaOrderService;
@Autowired
lateinit var mapper: OrderMapper


@ApiOperation(value = "订单查询",notes = "订单列表查询")
@RequestMapping(value = "/findAllOrder",method = arrayOf(RequestMethod.POST))
fun findAllOrder(@ApiParam(name="order",value = "订单",required = true) @RequestBody order: CaOrder):List<CaOrder>{
return service.findAllOrder(order);
}

@ApiOperation(value = "订单查询",notes = "订单列表查询")
@RequestMapping(value = "/find",method = arrayOf(RequestMethod.POST))
fun find(@ApiParam(name="order",value = "订单",required = true) @RequestBody order: CaOrder):String{
var orders: List<CaOrder> = mapper.findOrderList(order);


return "ssssssssssss"+orders.toString();
}

@ApiOperation(value = "新增订单",notes = "新增订单")
@RequestMapping(value = "/save",method = arrayOf(RequestMethod.POST))
fun save(@ApiParam(name="order",value = "订单",required = true) @RequestBody order: CaOrder):Int{
return service.saveOrder(order);
}

@ApiOperation(value = "修改订单",notes = "修改订单")
@RequestMapping(value = "/update",method = arrayOf(RequestMethod.POST))
fun update(@ApiParam(name="order",value = "订单",required = true) @RequestBody order: CaOrder):Int{
return service.updateOrder(order);
}


@ApiOperation(value = "根据id删除订单",notes = "根据id删除订单")
@RequestMapping(value = "/delete",method = arrayOf(RequestMethod.GET))
fun delete(@ApiParam(name="id",value = "订单id",required = true) @RequestParam(value = "id") id:Int){
service.deleteOrder(id);
}
}
访问

输入http://localhost:8090/demo/swagger-ui.html地址就可以看到了,新版本的swagger界面做了改版。 收起阅读 »

Kotlin+SpringBoot服务端restful框架搭建(2)集成mybatis

搭建完成简单的kotlin集成SpringBoot的框架,我们再来尝试把mybatis也集成进去,数据库我们采用mysql。
 
要求
  • mybatis
  • mysql


快速搭建

1.创建一张表,表名ca_order
  • ID int
  • 订单编号 order_no varchar(10)
  • 订单金额 order_amount double
  • 订单创建时间 create_time datetime
  • 订单创建人 create_user varchar(10)
  • 支付方式 pay_type varchar(10)
  • 商品名称 commodity_name varchar(30)
  • 商品数量 commodity_num int

 
DROP TABLE IF EXISTS `ca_order`;
CREATE TABLE `ca_order` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`order_no` varchar(20) DEFAULT NULL,
`order_amount` double(10,2) DEFAULT NULL,
`create_time` datetime DEFAULT NULL,
`create_user` varchar(20) DEFAULT NULL,
`pay_type` varchar(10) DEFAULT NULL,
`commodity_name` varchar(20) DEFAULT NULL,
`commodity_num` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


INSERT INTO ca_order (order_no, order_amount, create_time, create_user, pay_type, commodity_name, commodity_num) VALUES ('1001', 1000, NOW(), '张三', '支付宝', '手机', 1);
INSERT INTO ca_order (order_no, order_amount, create_time, create_user, pay_type, commodity_name, commodity_num) VALUES ('1002', 2799.00, NOW(), '张小凡', '支付宝','荣耀v10',1);
INSERT INTO ca_order (order_no, order_amount, create_time, create_user, pay_type, commodity_name, commodity_num) VALUES ('1003', 16863.00, NOW(), '郭靖', '银联', 'iPhoneX', 2);
INSERT INTO ca_order (order_no, order_amount, create_time, create_user, pay_type, commodity_name, commodity_num) VALUES ('1004', 2677.00, NOW(), '张三风', '支付宝', 'vivoX21',1);
INSERT INTO ca_order (order_no, order_amount, create_time, create_user, pay_type, commodity_name, commodity_num) VALUES ('1005', 4325.78, NOW(), '谢逊', '微信', '诺基亚', 3);
INSERT INTO ca_order (order_no, order_amount, create_time, create_user, pay_type, commodity_name, commodity_num) VALUES ('1006', 2001, NOW(), '杨过', '支付宝', '小米mix', 2);
INSERT INTO ca_order (order_no, order_amount, create_time, create_user, pay_type, commodity_name, commodity_num) VALUES ('1007', 4399.00, NOW(), '张无忌', '微信', '华为P20',1);
INSERT INTO ca_order (order_no, order_amount, create_time, create_user, pay_type, commodity_name, commodity_num) VALUES ('1008', 2999, NOW(), '陈震', '支付宝', '荣耀v9', 3);
INSERT INTO ca_order (order_no, order_amount, create_time, create_user, pay_type, commodity_name, commodity_num) VALUES ('1009', 1999, NOW(), '李狗蛋', '信用卡', '小米6',1);
INSERT INTO ca_order (order_no, order_amount, create_time, create_user, pay_type, commodity_name, commodity_num) VALUES ('1010', 3200, NOW(), '郭德纲', '支付宝', 'iPhone6s', 1);

2.在application.yml添加datasource
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/csdata?useUnicode=true&characterEncoding=utf-8
username: root
password: 123456
driverClassName: com.mysql.jdbc.Driver
引入我们需要的mybatis和mysql
 <dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.34</version>
</dependency>
3.创建实体类。kotlin创建实体类方式有两种,一种是类似java的class,一种是kotlin的data class(数据类)。数据类(data class)必须满足以下要求:
  • 主构造函数至少有一个参数;
  • 主构造函数的所有参数需标记为val 或 var;
  • 数据类不能是抽象、开放、密封或者内部的;
  • 自kotlin 1.1起,数据类可以扩展其他类;在1.1之前,数据类只能实现接口


编译器会为数据类(data class)自动生成以下函数:
  • equals()/hashCode()
  • toString()
  • componentN()
  • copy()


lateinit只能用于非基本数据类型。Kotlin会使用null来对每一个用lateinit修饰的属性做初始化,而基础类型是没有null类型。
 
class
class CaOrder {
var id:Int=0
var orderNo:String=""
var orderAmount:Double=0.00
var createTime:String=""
var createUser:String=""
var payType:String=""
var commodityName:String=""
var commodityNum:Int=0
}
开始使用lateinit var定义属性,但是运行的时候提示lateinit property has not been initialized,目前没找到解决方法,就直接给属性设置个默认值了
 
data class
 
data class CaOrder(
var id:Int?,
var orderNo:String,
var orderAmount:Double?,
var createTime:String,
var createUser:String,
var payType:String,
var commodityName:String,
var commodityNum:Int?
)
注意:Int后面的?号,如果不加这个问号,运行的时候会报No constructor found in void matching的错误。原因是Int是kotlin的基础数据类型不能为null,会被映射成java中int,而实体类对应数据的时候某些字段会出现空值的,这就使kotlin在转成实体类的时候不确定转成int还是Integer,而加上问号之后是告诉它这个属性为空值的时候就返回null。具体可以参考一下kotlin的?的使用方法。
 
4.创建Mapper,两种方式来实现Mapper,一种是通过注解标签@select,@insert,@update,@delete,另一种通过xml配置文件,还是推荐使用xml吧,使用起来相对方便,动态sql写起来更容易。
 
第一种。

实体类CaOrderDao
 
package com.kotliner.demo.mapper

import com.kotliner.demo.entity.CaOrder
import org.apache.ibatis.annotations.*

@Mapper
interface CaOrderMapper{

@Select("""
select id,order_no as orderNo, order_amount, date_format(create_time,'%Y-%m-%d %H:%i:%s') as create_time, create_user, pay_type, commodity_name, commodity_num from ca_order
""")
fun findOrderList(order: CaOrder):List<CaOrder>;


@Insert("""
INSERT INTO ca_order (order_no, order_amount, create_time, create_user, pay_type, commodity_name, commodity_num) VALUES
(#{orderNo},#{orderAmount},NOW(),#{createUser},#{payType},#{commodityName},#{commodityNum})
""")
fun saveOrder(order: CaOrder):Int;


@Update("""
update ca_order set order_amount=#{orderAmount} where id=#{id}
""")
fun updateOrder(order: CaOrder):Int;

@Delete("""
delete from ca_order where id=#{id}
""")
fun deleteOrder(id:Int)
}
第二种,如果使用这种需要再application.yml添加如下代码用来指定xml位置
 
mybatis:
type-aliases-package: com.kotliner.demo.entity
mapper-locations: classpath:mapper/*.xml
这时候mapperr类就变得简单了
 
package com.kotliner.demo.mapper

import com.kotliner.demo.entity.CaOrder
import org.apache.ibatis.annotations.Mapper

@Mapper
interface CaOrderMapper{

fun findOrderList(order: CaOrder):List<CaOrder>;
fun saveOrder(order: CaOrder):Int;
fun updateOrder(order: CaOrder):Int;
fun deleteOrder(id:Int);
}
然后在resource下面创建Mapper文件,放入xml文件
<mapper namespace="com.kotliner.demo.mapper.OrderMapper">

<!-- 实体类映射-->
<resultMap type="com.kotliner.demo.entity.CaOrder" id="OrderMap">
<result column="id" property="id"/>
<result column="order_no" property="orderNo"/>
<result column="order_amount" property="orderAmount"/>
<result column="create_time" property="createTime"/>
<result column="create_user" property="createUser"/>
<result column="pay_type" property="payType"/>
<result column="commodity_name" property="commodityName"/>
<result column="commodity_num" property="commodityNum"/>
</resultMap>
<!-- 按条件查询-->

<select id="findOrderList" parameterType="com.kotliner.demo.entity.CaOrder" resultMap="OrderMap" >
select id,order_no, order_amount, create_time, create_user, pay_type, commodity_name, commodity_num from ca_order
</select>


</mapper>
5.创建service和controller
 
服务接口ICaOrderService
package com.kotliner.demo.service

import com.kotliner.demo.entity.CaOrder


interface ICaOrderService{

fun findAllOrder(order: CaOrder):List<CaOrder>;

fun saveOrder(order: CaOrder):Int;

fun updateOrder(order: CaOrder):Int;

fun deleteOrder(id: Int);
}
服务实现类CaOrderMapper
 
package com.kotliner.demo.service


import com.kotliner.demo.entity.CaOrder
import com.kotliner.demo.mapper.CaOrderMapper
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service


@Service
class CaOrderImpl : ICaOrderService {

@Autowired
lateinit var dao: CaOrderMapper;

override fun findAllOrder(order: CaOrder): List<CaOrder> {
return dao.findOrderList(order);

}

override fun saveOrder(order: CaOrder): Int {
return dao.saveOrder(order);
}

override fun updateOrder(order: CaOrder): Int {
return dao.updateOrder(order);
}

override fun deleteOrder(id: Int) {
dao.deleteOrder(id);
}

}
注解的使用同java相同,只是具体方法属性定义需要注意
 
OrderController类
 
package com.kotliner.demo.controller

import com.kotliner.demo.entity.CaOrder
import com.kotliner.demo.mapper.OrderMapper
import com.kotliner.demo.service.ICaOrderService
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.web.bind.annotation.*


@RestController
class OrderController{

@Autowired
lateinit var service: ICaOrderService


@RequestMapping(value = "/findAllOrder",method = arrayOf(RequestMethod.POST))
fun findAllOrder(@RequestBody order: CaOrder):List<CaOrder>{
return service.findAllOrder(order);
}

@RequestMapping(value = "/save",method = arrayOf(RequestMethod.POST))
fun save(@RequestBody order: CaOrder):Int{
return service.saveOrder(order);
}

@RequestMapping(value = "/update",method = arrayOf(RequestMethod.POST))
fun update(@RequestBody order: CaOrder):Int{
return service.updateOrder(order);
}
@RequestMapping(value = "/delete",method = arrayOf(RequestMethod.GET))
fun delete(@RequestParam(value = "id") id:Int){
service.deleteOrder(id);
}
}
创建完成,启动一下服务。

创建的接口基本都是post的方式,我们通过postman来调试接口。
继续阅读 »
搭建完成简单的kotlin集成SpringBoot的框架,我们再来尝试把mybatis也集成进去,数据库我们采用mysql。
 
要求
  • mybatis
  • mysql


快速搭建

1.创建一张表,表名ca_order
  • ID int
  • 订单编号 order_no varchar(10)
  • 订单金额 order_amount double
  • 订单创建时间 create_time datetime
  • 订单创建人 create_user varchar(10)
  • 支付方式 pay_type varchar(10)
  • 商品名称 commodity_name varchar(30)
  • 商品数量 commodity_num int

 
DROP TABLE IF EXISTS `ca_order`;
CREATE TABLE `ca_order` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`order_no` varchar(20) DEFAULT NULL,
`order_amount` double(10,2) DEFAULT NULL,
`create_time` datetime DEFAULT NULL,
`create_user` varchar(20) DEFAULT NULL,
`pay_type` varchar(10) DEFAULT NULL,
`commodity_name` varchar(20) DEFAULT NULL,
`commodity_num` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


INSERT INTO ca_order (order_no, order_amount, create_time, create_user, pay_type, commodity_name, commodity_num) VALUES ('1001', 1000, NOW(), '张三', '支付宝', '手机', 1);
INSERT INTO ca_order (order_no, order_amount, create_time, create_user, pay_type, commodity_name, commodity_num) VALUES ('1002', 2799.00, NOW(), '张小凡', '支付宝','荣耀v10',1);
INSERT INTO ca_order (order_no, order_amount, create_time, create_user, pay_type, commodity_name, commodity_num) VALUES ('1003', 16863.00, NOW(), '郭靖', '银联', 'iPhoneX', 2);
INSERT INTO ca_order (order_no, order_amount, create_time, create_user, pay_type, commodity_name, commodity_num) VALUES ('1004', 2677.00, NOW(), '张三风', '支付宝', 'vivoX21',1);
INSERT INTO ca_order (order_no, order_amount, create_time, create_user, pay_type, commodity_name, commodity_num) VALUES ('1005', 4325.78, NOW(), '谢逊', '微信', '诺基亚', 3);
INSERT INTO ca_order (order_no, order_amount, create_time, create_user, pay_type, commodity_name, commodity_num) VALUES ('1006', 2001, NOW(), '杨过', '支付宝', '小米mix', 2);
INSERT INTO ca_order (order_no, order_amount, create_time, create_user, pay_type, commodity_name, commodity_num) VALUES ('1007', 4399.00, NOW(), '张无忌', '微信', '华为P20',1);
INSERT INTO ca_order (order_no, order_amount, create_time, create_user, pay_type, commodity_name, commodity_num) VALUES ('1008', 2999, NOW(), '陈震', '支付宝', '荣耀v9', 3);
INSERT INTO ca_order (order_no, order_amount, create_time, create_user, pay_type, commodity_name, commodity_num) VALUES ('1009', 1999, NOW(), '李狗蛋', '信用卡', '小米6',1);
INSERT INTO ca_order (order_no, order_amount, create_time, create_user, pay_type, commodity_name, commodity_num) VALUES ('1010', 3200, NOW(), '郭德纲', '支付宝', 'iPhone6s', 1);

2.在application.yml添加datasource
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/csdata?useUnicode=true&characterEncoding=utf-8
username: root
password: 123456
driverClassName: com.mysql.jdbc.Driver
引入我们需要的mybatis和mysql
 <dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.34</version>
</dependency>
3.创建实体类。kotlin创建实体类方式有两种,一种是类似java的class,一种是kotlin的data class(数据类)。数据类(data class)必须满足以下要求:
  • 主构造函数至少有一个参数;
  • 主构造函数的所有参数需标记为val 或 var;
  • 数据类不能是抽象、开放、密封或者内部的;
  • 自kotlin 1.1起,数据类可以扩展其他类;在1.1之前,数据类只能实现接口


编译器会为数据类(data class)自动生成以下函数:
  • equals()/hashCode()
  • toString()
  • componentN()
  • copy()


lateinit只能用于非基本数据类型。Kotlin会使用null来对每一个用lateinit修饰的属性做初始化,而基础类型是没有null类型。
 
class
class CaOrder {
var id:Int=0
var orderNo:String=""
var orderAmount:Double=0.00
var createTime:String=""
var createUser:String=""
var payType:String=""
var commodityName:String=""
var commodityNum:Int=0
}
开始使用lateinit var定义属性,但是运行的时候提示lateinit property has not been initialized,目前没找到解决方法,就直接给属性设置个默认值了
 
data class
 
data class CaOrder(
var id:Int?,
var orderNo:String,
var orderAmount:Double?,
var createTime:String,
var createUser:String,
var payType:String,
var commodityName:String,
var commodityNum:Int?
)
注意:Int后面的?号,如果不加这个问号,运行的时候会报No constructor found in void matching的错误。原因是Int是kotlin的基础数据类型不能为null,会被映射成java中int,而实体类对应数据的时候某些字段会出现空值的,这就使kotlin在转成实体类的时候不确定转成int还是Integer,而加上问号之后是告诉它这个属性为空值的时候就返回null。具体可以参考一下kotlin的?的使用方法。
 
4.创建Mapper,两种方式来实现Mapper,一种是通过注解标签@select,@insert,@update,@delete,另一种通过xml配置文件,还是推荐使用xml吧,使用起来相对方便,动态sql写起来更容易。
 
第一种。

实体类CaOrderDao
 
package com.kotliner.demo.mapper

import com.kotliner.demo.entity.CaOrder
import org.apache.ibatis.annotations.*

@Mapper
interface CaOrderMapper{

@Select("""
select id,order_no as orderNo, order_amount, date_format(create_time,'%Y-%m-%d %H:%i:%s') as create_time, create_user, pay_type, commodity_name, commodity_num from ca_order
""")
fun findOrderList(order: CaOrder):List<CaOrder>;


@Insert("""
INSERT INTO ca_order (order_no, order_amount, create_time, create_user, pay_type, commodity_name, commodity_num) VALUES
(#{orderNo},#{orderAmount},NOW(),#{createUser},#{payType},#{commodityName},#{commodityNum})
""")
fun saveOrder(order: CaOrder):Int;


@Update("""
update ca_order set order_amount=#{orderAmount} where id=#{id}
""")
fun updateOrder(order: CaOrder):Int;

@Delete("""
delete from ca_order where id=#{id}
""")
fun deleteOrder(id:Int)
}
第二种,如果使用这种需要再application.yml添加如下代码用来指定xml位置
 
mybatis:
type-aliases-package: com.kotliner.demo.entity
mapper-locations: classpath:mapper/*.xml
这时候mapperr类就变得简单了
 
package com.kotliner.demo.mapper

import com.kotliner.demo.entity.CaOrder
import org.apache.ibatis.annotations.Mapper

@Mapper
interface CaOrderMapper{

fun findOrderList(order: CaOrder):List<CaOrder>;
fun saveOrder(order: CaOrder):Int;
fun updateOrder(order: CaOrder):Int;
fun deleteOrder(id:Int);
}
然后在resource下面创建Mapper文件,放入xml文件
<mapper namespace="com.kotliner.demo.mapper.OrderMapper">

<!-- 实体类映射-->
<resultMap type="com.kotliner.demo.entity.CaOrder" id="OrderMap">
<result column="id" property="id"/>
<result column="order_no" property="orderNo"/>
<result column="order_amount" property="orderAmount"/>
<result column="create_time" property="createTime"/>
<result column="create_user" property="createUser"/>
<result column="pay_type" property="payType"/>
<result column="commodity_name" property="commodityName"/>
<result column="commodity_num" property="commodityNum"/>
</resultMap>
<!-- 按条件查询-->

<select id="findOrderList" parameterType="com.kotliner.demo.entity.CaOrder" resultMap="OrderMap" >
select id,order_no, order_amount, create_time, create_user, pay_type, commodity_name, commodity_num from ca_order
</select>


</mapper>
5.创建service和controller
 
服务接口ICaOrderService
package com.kotliner.demo.service

import com.kotliner.demo.entity.CaOrder


interface ICaOrderService{

fun findAllOrder(order: CaOrder):List<CaOrder>;

fun saveOrder(order: CaOrder):Int;

fun updateOrder(order: CaOrder):Int;

fun deleteOrder(id: Int);
}
服务实现类CaOrderMapper
 
package com.kotliner.demo.service


import com.kotliner.demo.entity.CaOrder
import com.kotliner.demo.mapper.CaOrderMapper
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service


@Service
class CaOrderImpl : ICaOrderService {

@Autowired
lateinit var dao: CaOrderMapper;

override fun findAllOrder(order: CaOrder): List<CaOrder> {
return dao.findOrderList(order);

}

override fun saveOrder(order: CaOrder): Int {
return dao.saveOrder(order);
}

override fun updateOrder(order: CaOrder): Int {
return dao.updateOrder(order);
}

override fun deleteOrder(id: Int) {
dao.deleteOrder(id);
}

}
注解的使用同java相同,只是具体方法属性定义需要注意
 
OrderController类
 
package com.kotliner.demo.controller

import com.kotliner.demo.entity.CaOrder
import com.kotliner.demo.mapper.OrderMapper
import com.kotliner.demo.service.ICaOrderService
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.web.bind.annotation.*


@RestController
class OrderController{

@Autowired
lateinit var service: ICaOrderService


@RequestMapping(value = "/findAllOrder",method = arrayOf(RequestMethod.POST))
fun findAllOrder(@RequestBody order: CaOrder):List<CaOrder>{
return service.findAllOrder(order);
}

@RequestMapping(value = "/save",method = arrayOf(RequestMethod.POST))
fun save(@RequestBody order: CaOrder):Int{
return service.saveOrder(order);
}

@RequestMapping(value = "/update",method = arrayOf(RequestMethod.POST))
fun update(@RequestBody order: CaOrder):Int{
return service.updateOrder(order);
}
@RequestMapping(value = "/delete",method = arrayOf(RequestMethod.GET))
fun delete(@RequestParam(value = "id") id:Int){
service.deleteOrder(id);
}
}
创建完成,启动一下服务。

创建的接口基本都是post的方式,我们通过postman来调试接口。 收起阅读 »

为什么我要改用Kotlin?


写在前面的话,作为一个不熬夜的人,一觉醒来发现Kotlin成为了Android的官方语言,可谓是大喜过望。为了趁热打铁,我决定提前三天放出原定本周日Release的文章。希望能及时让大家了解一下Kotlin。

相信很多开发人员,尤其是Android开发者都会或多或少听说过Kotlin,当然如果没有听过或者不熟悉也没有关系。因为本篇文章以及博客后期的内容会涉及到很多关于Kotlin的知识分享。

在写这篇文章前的一个多月,Flipboard中国的Android项目确定了正式将Kotlin作为项目开发语言,这就意味着新增的代码文件将以Kotlin代码格式出现,而且同时旧的Java代码也将会陆陆续续翻译成Kotlin代码。在使用Kotlin的这段时间,被它的简洁,高效,快捷等等特点震撼,所以有必要写一篇文章来谈一谈Kotlin的特性,如若能取得推广Kotlin的效果则倍感欣慰。 


Kotlin的“简历”

来自于著名的IDE IntelliJ IDEA(Android Studio基于此开发) 软件开发公司 JetBrains(位于东欧捷克)
起源来自JetBrains的圣彼得堡团队,名称取自圣彼得堡附近的一个小岛(Kotlin Island)
一种基于JVM的静态类型编程语言

来自知名的工具开发商JetBrains,也就决定了Kotlin的基因中必然包含实用与高效等特征。那我们接下来看一看Kotlin的特点,当然这也是我改用Kotlin的重要原因。

语法简单,不啰嗦
//variables and constants
var currentVersionCode = 1 //变量当前的版本号,类型Int可以根据值推断出来
var currentVersionName : String = "1.0" //显式标明类型
val APPNAME = "droidyue.com" //常量APPNAME 类型(String)可以根据值推断出来

//methods
fun main(args: Array<String>) {
println(args)
}

// class
class MainActivity : AppCompatActivity() {

}

// data class 自动生成getter,setting,hashcode和equals等方法
data class Book(var name: String, val price: Float, var author: String)

//支持默认参数值,减少方法重载
fun Context.showToast(message: String, duration:Int = Toast.LENGTH_LONG) {
Toast.makeText(this, message, duration).show()
}

  • Kotlin支持类型推断,没有Java那样的啰嗦。
  • 另外用var表示变量,val表示常量更加的简洁
  • 方法也很简单,连function都缩写成了fun,平添了几分双关之意。
  • 类的继承和实现很简单,使用:即可
  • Kotlin每个句子都不需要加分号(;)

 
空指针安全

空指针(NullPointerException或NPE)是我们使用Java开发程序中最常见的崩溃了。因为在Java中我们不得不写很多防御性的代码,比如这样
public void test(String string) {
if (string != null) {
char chars = string.toCharArray();
if (chars.length > 10) {
System.out.println(((Character)chars[10]).hashCode());
}
}
}
在Kotlin中空指针异常得到了很好的解决。
  • 在类型上的处理,即在类型后面加上,即表示这个变量或参数以及返回值可以为null,否则不允许为变量参数赋值为null或者返回null
  • 对于一个可能是null的变量或者参数,在调用对象方法或者属性之前,需要加上,否则编译无法通过。


如下面的代码就是Kotlin实现空指针安全的一个例子,而且相对Java实现而言,简直是一行代码搞定的。
fun testNullSafeOperator(string: String?) {
System.out.println(string?.toCharArray()?.getOrNull(10)?.hashCode())
}

testNullSafeOperator(null)
testNullSafeOperator("12345678901")
testNullSafeOperator("123")

//result
null
49
null
支持方法扩展
很多时候,Framework提供给我们的API往往都时比较原子的,调用时需要我们进行组合处理,因为就会产生了一些Util类,一个简单的例子,我们想要更快捷的展示Toast信息,在Java中我们可以这样做。
public static void longToast(Context context, String message) {
Toast.makeText(context, message, Toast.LENGTH_LONG).show();
}
但是Kotlin的实现却让人惊奇,我们只需要重写扩展方法就可以了,比如这个longToast方法扩展到所有的Context对象中,如果不去追根溯源,可能无法区分是Framework提供的还是自行扩展的。
fun Context.longToast(message: String) {
Toast.makeText(this, message, Toast.LENGTH_LONG).show()
}
applicationContext.longToast("hello world")
注意:Kotlin的方法扩展并不是真正修改了对应的类文件,而是在编译器和IDE方面做得处理。使我们看起来像是扩展了方法。
Lambda, 高阶函数,Streams API, 函数式编程支持
所谓的Lambda表达式是匿名函数,这使得我们的代码会更加的简单。比如下面的代码就是lambda的应用。
findViewById(R.id.content).setOnClickListener {
Log.d("MainActivity", "$it was clicked")
}
所谓的高阶函数就是
  • 可以接受函数作为参数
  • 也可以返回函数作为结果

举一个接受函数作为参数的例子。在Android开发中,我们经常使用SharedPreference来存储数据,如果忘记调用apply或者commit则数据修改不能应用。利用Kotlin中的高阶函数的功能,我们能更好的解决这个问题
fun SharedPreferences.editor(f: (SharedPreferences.Editor) -> Unit) {
val editor = edit()
f(editor)
editor.apply()
}

//实际调用
PreferenceManager.getDefaultSharedPreferences(this).editor {
it.putBoolean("installed", true)
}
当然这上面的例子中我们也同时使用了方法扩展这个特性。

Kotlin支持了Streams API和方法引用,这样函数式编程更加方便。比如下面的代码就是我们结合Jsoup,来抓取某个proxy网站的数据,代码更加简单,实现起来也快速。
fun parse(url: String): Unit {
Jsoup.parse(URL(url), PARSE_URL_TIMEOUT).getElementsByClass("table table-sm")
.first().children()
.filter { "tbody".equals(it.tagName().toLowerCase()) }
.flatMap(Element::children).forEach {
trElement ->
ProxyItem().apply {
trElement.children().forEachIndexed { index, element ->
when (index) {
0 -> {
host = element.text().split(":")[0]
port = element.text().split(":")[1].toInt()
}
1 -> protocol = element.text()
5 -> country = element.text()
}
}
}.let(::println)
}
}
字符串模板
无论是Java还是Android开发,我们都会用到字符串拼接,比如进行日志输出等等。在Kotlin中,字符串模板是支持的,我们可以很轻松的完成一个字符串数组的组成
val book = Book("Thinking In Java", 59.0f, "Unknown")
val extraValue = "extra"
Log.d("MainActivity", "book.name = ${book.name}; book.price=${book.price};extraValue=$extraValue")
与Java交互性好
Kotlin和Java都属于基于JVM的编程语言。Kotlin和Java的交互性很好,可以说是无缝连接。这表现在
  • Kotlin可以自由的引用Java的代码,反之亦然。
  • Kotlin可以现有的全部的Java框架和库
  • Java文件可以很轻松的借助IntelliJ的插件转成kotlin

​Kotlin应用广泛​
 
Kotlin对Android应用开发支持广泛,诸多工具,比如kotterknife(ButterKnife Kotlin版),RxKotlin,Anko等等,当然还有已经存在的很多Java的库都是可以使用的。

除此之外,Kotlin也可以编译成Javascript。最近使用Kotlin写了一段抓取proxy的代码,实现起来非常快捷。甚至比纯JavaScript实现起来要快很多。
fun handle(): Unit {
window.onload = {
document.getElementsByClassName("table table-sm").asList().first()
.children.asList().filter { "TBODY".equals(it.tagName.toUpperCase()) }
.flatMap { it.children.asList() }.forEach {
var proxyItem = ProxyItem()
it.children.asList().forEachIndexed { index, element ->
when (index) {
0 -> {
proxyItem.host = element.trimedTextContent()?.split(":")?.get(0) ?: ""
proxyItem.port = element.trimedTextContent()?.split(":")?.get(1)?.trim()?.toInt() ?: -1
}
1 -> proxyItem.protocol = element.trimedTextContent() ?: ""
5 -> proxyItem.country = element.trimedTextContent() ?: ""
}
}.run {
console.info("proxyItem $proxyItem")
}

}
}
}
关于性能
Kotlin的执行效率和Java代码的执行效率理论上一致的。有时候Kotlin可能会显得高一些,比如Kotlin提供了方法的inline设置,可以设置某些高频方法进行inline操作,减少了运行时的进栈出栈和保存状态的开销。

读到这里,是不是想要尝试一下Kotlin呢,它简洁的语法,汇集诸多特性,高效率实现等等,已经在国外风生水起,国外的Pintereset, Square, Flipboard等公司已经开始应用到生产中。
关于转向Kotlin
其实,我在做决定之前(当时Kotlin还没有被钦定)也曾有过考虑,是不是选择了Kotlin就意味着放弃Java呢,冷静下来想一想,其实并不是那么回事,因为Kotlin与Java语法太相近,以及在Kotlin中无时无刻不在和Java相关的东西打交道,所以这点顾虑不是问题的。

对于个人的项目来转向Kotlin,通常不是很难的选择,毕竟Kotlin是那么优秀的语言,相信很多人还是愿意尝试并使用这个事半功倍的语言的。

而比较难抉择的情况是如果如何让团队转用Kotlin,个人认为团队难以转用的原因有很多,比如学习成本,历史包袱等等。但其实根本原因还是思维方式的问题,歪果仁喜欢用工具来提升开发效率,因为人力成本很高。而国内团队提高效率的办法通常是增加成员。好在Flipboard 美国团队自2015年(可能更早)就引入了Kotlin,因此中国团队这边选用Kotlin也更加顺水推舟。当然更主要的是目前团队规模不大,成员一致认可Kotlin的优点。

关于团队转用Kotlin的方法,一般比较行得通的办法是自上而下的推行。这就意味着要么直接的技术负责人比较开明要么就是需要有人来不断推介来影响团队。

做个比较现实的比拟,Java就像是一趟从我的家乡保定开往北京西的耗时将近2个小时甚至更长的普通列车,而Kotlin则是那趟仅需40分钟就能到达的高铁。通常的人都会选择高铁,因为它节省了时间和提高了体验。这个时间和体验对应编程中的,我想应该是高效率和高可读性,可维护性的代码。

现在好了,有了Google的支持,Kotlin转Android相信在不久的将来就会全面展开。篡改Python的一句名言“人生苦短,我用Kotlin”,这样一个高效实用的语言应该会被越来越多的团队所接受,并应用到开发生产中。当然也希望在国内环境下大放异彩。
 
转载自:https://blog.csdn.net/androidy ... 57157
继续阅读 »

写在前面的话,作为一个不熬夜的人,一觉醒来发现Kotlin成为了Android的官方语言,可谓是大喜过望。为了趁热打铁,我决定提前三天放出原定本周日Release的文章。希望能及时让大家了解一下Kotlin。

相信很多开发人员,尤其是Android开发者都会或多或少听说过Kotlin,当然如果没有听过或者不熟悉也没有关系。因为本篇文章以及博客后期的内容会涉及到很多关于Kotlin的知识分享。

在写这篇文章前的一个多月,Flipboard中国的Android项目确定了正式将Kotlin作为项目开发语言,这就意味着新增的代码文件将以Kotlin代码格式出现,而且同时旧的Java代码也将会陆陆续续翻译成Kotlin代码。在使用Kotlin的这段时间,被它的简洁,高效,快捷等等特点震撼,所以有必要写一篇文章来谈一谈Kotlin的特性,如若能取得推广Kotlin的效果则倍感欣慰。 


Kotlin的“简历”

来自于著名的IDE IntelliJ IDEA(Android Studio基于此开发) 软件开发公司 JetBrains(位于东欧捷克)
起源来自JetBrains的圣彼得堡团队,名称取自圣彼得堡附近的一个小岛(Kotlin Island)
一种基于JVM的静态类型编程语言

来自知名的工具开发商JetBrains,也就决定了Kotlin的基因中必然包含实用与高效等特征。那我们接下来看一看Kotlin的特点,当然这也是我改用Kotlin的重要原因。

语法简单,不啰嗦
//variables and constants
var currentVersionCode = 1 //变量当前的版本号,类型Int可以根据值推断出来
var currentVersionName : String = "1.0" //显式标明类型
val APPNAME = "droidyue.com" //常量APPNAME 类型(String)可以根据值推断出来

//methods
fun main(args: Array<String>) {
println(args)
}

// class
class MainActivity : AppCompatActivity() {

}

// data class 自动生成getter,setting,hashcode和equals等方法
data class Book(var name: String, val price: Float, var author: String)

//支持默认参数值,减少方法重载
fun Context.showToast(message: String, duration:Int = Toast.LENGTH_LONG) {
Toast.makeText(this, message, duration).show()
}

  • Kotlin支持类型推断,没有Java那样的啰嗦。
  • 另外用var表示变量,val表示常量更加的简洁
  • 方法也很简单,连function都缩写成了fun,平添了几分双关之意。
  • 类的继承和实现很简单,使用:即可
  • Kotlin每个句子都不需要加分号(;)

 
空指针安全

空指针(NullPointerException或NPE)是我们使用Java开发程序中最常见的崩溃了。因为在Java中我们不得不写很多防御性的代码,比如这样
public void test(String string) {
if (string != null) {
char chars = string.toCharArray();
if (chars.length > 10) {
System.out.println(((Character)chars[10]).hashCode());
}
}
}
在Kotlin中空指针异常得到了很好的解决。
  • 在类型上的处理,即在类型后面加上,即表示这个变量或参数以及返回值可以为null,否则不允许为变量参数赋值为null或者返回null
  • 对于一个可能是null的变量或者参数,在调用对象方法或者属性之前,需要加上,否则编译无法通过。


如下面的代码就是Kotlin实现空指针安全的一个例子,而且相对Java实现而言,简直是一行代码搞定的。
fun testNullSafeOperator(string: String?) {
System.out.println(string?.toCharArray()?.getOrNull(10)?.hashCode())
}

testNullSafeOperator(null)
testNullSafeOperator("12345678901")
testNullSafeOperator("123")

//result
null
49
null
支持方法扩展
很多时候,Framework提供给我们的API往往都时比较原子的,调用时需要我们进行组合处理,因为就会产生了一些Util类,一个简单的例子,我们想要更快捷的展示Toast信息,在Java中我们可以这样做。
public static void longToast(Context context, String message) {
Toast.makeText(context, message, Toast.LENGTH_LONG).show();
}
但是Kotlin的实现却让人惊奇,我们只需要重写扩展方法就可以了,比如这个longToast方法扩展到所有的Context对象中,如果不去追根溯源,可能无法区分是Framework提供的还是自行扩展的。
fun Context.longToast(message: String) {
Toast.makeText(this, message, Toast.LENGTH_LONG).show()
}
applicationContext.longToast("hello world")
注意:Kotlin的方法扩展并不是真正修改了对应的类文件,而是在编译器和IDE方面做得处理。使我们看起来像是扩展了方法。
Lambda, 高阶函数,Streams API, 函数式编程支持
所谓的Lambda表达式是匿名函数,这使得我们的代码会更加的简单。比如下面的代码就是lambda的应用。
findViewById(R.id.content).setOnClickListener {
Log.d("MainActivity", "$it was clicked")
}
所谓的高阶函数就是
  • 可以接受函数作为参数
  • 也可以返回函数作为结果

举一个接受函数作为参数的例子。在Android开发中,我们经常使用SharedPreference来存储数据,如果忘记调用apply或者commit则数据修改不能应用。利用Kotlin中的高阶函数的功能,我们能更好的解决这个问题
fun SharedPreferences.editor(f: (SharedPreferences.Editor) -> Unit) {
val editor = edit()
f(editor)
editor.apply()
}

//实际调用
PreferenceManager.getDefaultSharedPreferences(this).editor {
it.putBoolean("installed", true)
}
当然这上面的例子中我们也同时使用了方法扩展这个特性。

Kotlin支持了Streams API和方法引用,这样函数式编程更加方便。比如下面的代码就是我们结合Jsoup,来抓取某个proxy网站的数据,代码更加简单,实现起来也快速。
fun parse(url: String): Unit {
Jsoup.parse(URL(url), PARSE_URL_TIMEOUT).getElementsByClass("table table-sm")
.first().children()
.filter { "tbody".equals(it.tagName().toLowerCase()) }
.flatMap(Element::children).forEach {
trElement ->
ProxyItem().apply {
trElement.children().forEachIndexed { index, element ->
when (index) {
0 -> {
host = element.text().split(":")[0]
port = element.text().split(":")[1].toInt()
}
1 -> protocol = element.text()
5 -> country = element.text()
}
}
}.let(::println)
}
}
字符串模板
无论是Java还是Android开发,我们都会用到字符串拼接,比如进行日志输出等等。在Kotlin中,字符串模板是支持的,我们可以很轻松的完成一个字符串数组的组成
val book = Book("Thinking In Java", 59.0f, "Unknown")
val extraValue = "extra"
Log.d("MainActivity", "book.name = ${book.name}; book.price=${book.price};extraValue=$extraValue")
与Java交互性好
Kotlin和Java都属于基于JVM的编程语言。Kotlin和Java的交互性很好,可以说是无缝连接。这表现在
  • Kotlin可以自由的引用Java的代码,反之亦然。
  • Kotlin可以现有的全部的Java框架和库
  • Java文件可以很轻松的借助IntelliJ的插件转成kotlin

​Kotlin应用广泛​
 
Kotlin对Android应用开发支持广泛,诸多工具,比如kotterknife(ButterKnife Kotlin版),RxKotlin,Anko等等,当然还有已经存在的很多Java的库都是可以使用的。

除此之外,Kotlin也可以编译成Javascript。最近使用Kotlin写了一段抓取proxy的代码,实现起来非常快捷。甚至比纯JavaScript实现起来要快很多。
fun handle(): Unit {
window.onload = {
document.getElementsByClassName("table table-sm").asList().first()
.children.asList().filter { "TBODY".equals(it.tagName.toUpperCase()) }
.flatMap { it.children.asList() }.forEach {
var proxyItem = ProxyItem()
it.children.asList().forEachIndexed { index, element ->
when (index) {
0 -> {
proxyItem.host = element.trimedTextContent()?.split(":")?.get(0) ?: ""
proxyItem.port = element.trimedTextContent()?.split(":")?.get(1)?.trim()?.toInt() ?: -1
}
1 -> proxyItem.protocol = element.trimedTextContent() ?: ""
5 -> proxyItem.country = element.trimedTextContent() ?: ""
}
}.run {
console.info("proxyItem $proxyItem")
}

}
}
}
关于性能
Kotlin的执行效率和Java代码的执行效率理论上一致的。有时候Kotlin可能会显得高一些,比如Kotlin提供了方法的inline设置,可以设置某些高频方法进行inline操作,减少了运行时的进栈出栈和保存状态的开销。

读到这里,是不是想要尝试一下Kotlin呢,它简洁的语法,汇集诸多特性,高效率实现等等,已经在国外风生水起,国外的Pintereset, Square, Flipboard等公司已经开始应用到生产中。
关于转向Kotlin
其实,我在做决定之前(当时Kotlin还没有被钦定)也曾有过考虑,是不是选择了Kotlin就意味着放弃Java呢,冷静下来想一想,其实并不是那么回事,因为Kotlin与Java语法太相近,以及在Kotlin中无时无刻不在和Java相关的东西打交道,所以这点顾虑不是问题的。

对于个人的项目来转向Kotlin,通常不是很难的选择,毕竟Kotlin是那么优秀的语言,相信很多人还是愿意尝试并使用这个事半功倍的语言的。

而比较难抉择的情况是如果如何让团队转用Kotlin,个人认为团队难以转用的原因有很多,比如学习成本,历史包袱等等。但其实根本原因还是思维方式的问题,歪果仁喜欢用工具来提升开发效率,因为人力成本很高。而国内团队提高效率的办法通常是增加成员。好在Flipboard 美国团队自2015年(可能更早)就引入了Kotlin,因此中国团队这边选用Kotlin也更加顺水推舟。当然更主要的是目前团队规模不大,成员一致认可Kotlin的优点。

关于团队转用Kotlin的方法,一般比较行得通的办法是自上而下的推行。这就意味着要么直接的技术负责人比较开明要么就是需要有人来不断推介来影响团队。

做个比较现实的比拟,Java就像是一趟从我的家乡保定开往北京西的耗时将近2个小时甚至更长的普通列车,而Kotlin则是那趟仅需40分钟就能到达的高铁。通常的人都会选择高铁,因为它节省了时间和提高了体验。这个时间和体验对应编程中的,我想应该是高效率和高可读性,可维护性的代码。

现在好了,有了Google的支持,Kotlin转Android相信在不久的将来就会全面展开。篡改Python的一句名言“人生苦短,我用Kotlin”,这样一个高效实用的语言应该会被越来越多的团队所接受,并应用到开发生产中。当然也希望在国内环境下大放异彩。
 
转载自:https://blog.csdn.net/androidy ... 57157 收起阅读 »

Kotlin+SpringBoot服务端restful框架搭建(1)

       本文的组要目的是完成SpringBoot集成Kotlin的一个基本项目构建,通过这个例子能够对kotlin有一个简单的了解。与其看着枯燥的教程,看看它的使用也许会更有意思。

kotlin简介
      Kotlin是一个基于JVM的编程语言,由JetBrains设计开发并开源。Kotlin可以编译成Java字节码也可以编译成JavaScript,支持开发Android,并且谷歌已经明确将Kotlin作为Android的一级开发语言。最新的Spring5版本也专门引入了对于Kotlin的支持。Kotlin拥有更简洁的代码,完全兼容java,而且同java可以实现完全的互调。使用Kotlin你起码可以少些30%的代码
 
要求
  • JDK 1.8
  • maven构建
  • Spring4
  • IDEA Intellij
  • Kotlin 1.2.31

 
快速构建
 
首先构建一个maven项目,我们命名为KotlinDemo。(使用idea构建Kotlin项目需要按照Kotlin的插件。)
1.先来修改pom.xml添加需要使用的依赖。 引入spring-boot-starter-parent,这里使用1.5.6版本
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.6.RELEASE</version>
</parent>
添加需要的依赖
 <properties>
<java.version>1.8</java.version>
<mybatis.spring.version>1.2.4</mybatis.spring.version>
<kotlin.compiler.incremental>true</kotlin.compiler.incremental>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<kotlin.version>1.2.31</kotlin.version>
</properties>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jre8</artifactId>
<version>${kotlin.version}</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-reflect</artifactId>
<version>${kotlin.version}</version>
</dependency>
在build中添加插件
 
<plugin>
<artifactId>kotlin-maven-plugin</artifactId>
<groupId>org.jetbrains.kotlin</groupId>
<version>1.2.31</version>
<configuration>
<compilerPlugins>
<plugin>spring</plugin>
</compilerPlugins>
<jvmTarget>1.8</jvmTarget>
</configuration>
<executions>
<execution>
<id>compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>test-compile</id>
<phase>test-compile</phase>
<goals>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-allopen</artifactId>
<version>1.2.31</version>
</dependency>
</dependencies>
</plugin>
2.创建application.yml
server:
context-path: /kotlin
port: 8090
3.创建Application.kt文件
 
       创建类的方法同java相似,也是引入各种包,但是需要注意Kotlin的main方法是class外面和java的main方法区别

        添加spring的注解@RestController和@SpringBootApplication,我们在class里面创建一个简单的restfull格式的请求方法hello(),方法返一个String的字符串。

       添加@RequestMapping时候需要注意设置method的时候,这里method接收的是一个数组,不是RequestMethod.GE,所以我们需要通过kotlin提供的arrayOf()方法转换一个下,这是一个创建数据的方法,具体的可以参考一下kotlin的文档。

       注意一下 SpringApplication.run中参数这个和java的区别有点大
 
Application.kt类代码
 
package demo

import org.springframework.boot.SpringApplication
@RestController
@SpringBootApplication
class Application{

@RequestMapping(value = "/hello",method =arrayOf(RequestMethod.GET))
fun hello(): String {

return "hello kotlin";

}
}

fun main(args: Array<String>){

//::符号是得到这个类的class对象
SpringApplication.run(Application::class.java,*args);

}
3.项目基本搭建完成,试试启动项目访问http://localhost:8090/demo/hello,页面会返回hello kotlin。

a.png

 
 
 
继续阅读 »
       本文的组要目的是完成SpringBoot集成Kotlin的一个基本项目构建,通过这个例子能够对kotlin有一个简单的了解。与其看着枯燥的教程,看看它的使用也许会更有意思。

kotlin简介
      Kotlin是一个基于JVM的编程语言,由JetBrains设计开发并开源。Kotlin可以编译成Java字节码也可以编译成JavaScript,支持开发Android,并且谷歌已经明确将Kotlin作为Android的一级开发语言。最新的Spring5版本也专门引入了对于Kotlin的支持。Kotlin拥有更简洁的代码,完全兼容java,而且同java可以实现完全的互调。使用Kotlin你起码可以少些30%的代码
 
要求
  • JDK 1.8
  • maven构建
  • Spring4
  • IDEA Intellij
  • Kotlin 1.2.31

 
快速构建
 
首先构建一个maven项目,我们命名为KotlinDemo。(使用idea构建Kotlin项目需要按照Kotlin的插件。)
1.先来修改pom.xml添加需要使用的依赖。 引入spring-boot-starter-parent,这里使用1.5.6版本
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.6.RELEASE</version>
</parent>
添加需要的依赖
 <properties>
<java.version>1.8</java.version>
<mybatis.spring.version>1.2.4</mybatis.spring.version>
<kotlin.compiler.incremental>true</kotlin.compiler.incremental>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<kotlin.version>1.2.31</kotlin.version>
</properties>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jre8</artifactId>
<version>${kotlin.version}</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-reflect</artifactId>
<version>${kotlin.version}</version>
</dependency>
在build中添加插件
 
<plugin>
<artifactId>kotlin-maven-plugin</artifactId>
<groupId>org.jetbrains.kotlin</groupId>
<version>1.2.31</version>
<configuration>
<compilerPlugins>
<plugin>spring</plugin>
</compilerPlugins>
<jvmTarget>1.8</jvmTarget>
</configuration>
<executions>
<execution>
<id>compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>test-compile</id>
<phase>test-compile</phase>
<goals>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-allopen</artifactId>
<version>1.2.31</version>
</dependency>
</dependencies>
</plugin>
2.创建application.yml
server:
context-path: /kotlin
port: 8090
3.创建Application.kt文件
 
       创建类的方法同java相似,也是引入各种包,但是需要注意Kotlin的main方法是class外面和java的main方法区别

        添加spring的注解@RestController和@SpringBootApplication,我们在class里面创建一个简单的restfull格式的请求方法hello(),方法返一个String的字符串。

       添加@RequestMapping时候需要注意设置method的时候,这里method接收的是一个数组,不是RequestMethod.GE,所以我们需要通过kotlin提供的arrayOf()方法转换一个下,这是一个创建数据的方法,具体的可以参考一下kotlin的文档。

       注意一下 SpringApplication.run中参数这个和java的区别有点大
 
Application.kt类代码
 
package demo

import org.springframework.boot.SpringApplication
@RestController
@SpringBootApplication
class Application{

@RequestMapping(value = "/hello",method =arrayOf(RequestMethod.GET))
fun hello(): String {

return "hello kotlin";

}
}

fun main(args: Array<String>){

//::符号是得到这个类的class对象
SpringApplication.run(Application::class.java,*args);

}
3.项目基本搭建完成,试试启动项目访问http://localhost:8090/demo/hello,页面会返回hello kotlin。

a.png

 
 
  收起阅读 »

使用Kotlin来开发Android,这些优缺点要考虑


 
Kotlin 语言说来也不是很新:是在 2011 年推出的,但火起来大家都知道是因为前几个月谷歌在 I / O 2017 上宣布它成为 Android 官方支持开发语言。自此之后,现在,Kotlin 开始出现在各个语言榜单之上,而且由于 JetBrains 和 Google 的企业支持基础,正迅速得到应用。

据 Kotlin 官方网站的信息,包括 Atlassian、Pivotal 、Uber、Pinterest、Evernote 等知名技术公司正在积极地将 Kotlin 用于 Android 应用开发。

如果你也正在考虑加入 Kotlin 的阵容,请确保已了解该技术的好处以及可能存在的陷阱。这里有一些关于 Kotlin 编程语言的见解,可供参考。

[使用Kotlin来开发Android,这些优缺点要考虑]

与已经发布 22 年的 Java 相比,Kotlin 有一些明显的改进:

提高团队的生产力

基于 Java 的 Kotlin 消除了其前身的过时和繁琐。语言紧凑、清晰、高效,语法简洁直观。因此,Kotlin 可以显着提高团队效率:编写和部署新代码所需的时间较少。这也有助于提高代码可维护性。

据 Keepsafe 的 Android 开发人员 A. J. Alt 所表示,将 “App Lock” 应用从 Java 转换为 Kotlin ,总代码量减少了 30% 。

与现有代码兼容

Kotlin 的优点之一是其 100% 的 Java 互操作性。该语言适用于 Java 本身,及所有相关工具和框架,提供了丰富的生态系统。这也使得可以选择逐渐迁移到 Kotlin ,或者在同一个项目中同时使用这两种语言。

可维护性

由 JetBrains 构建并支持,Kotlin 为许多 IDE(包括 Android Studio)提供了良好的支持。

更少的错误

通过更紧凑和更清晰的代码库,Kotlin 允许在生产中减少错误,生成更稳定的代码。编译器在编译时检测所有可能的错误,而不是运行时。这使得 Kotlin 成为比 Java 更安全的替代品。

可靠

不同于 Swift ,Kotlin 是一种更成熟的语言。在 2011 年推出后,在最终的 1.0 版本发布之前,经历了多个 Alfa 和 Beta 阶段。最新版本也与以前的版本反向兼容。

然而,在生产过程中使用 Kotlin 之前,仍需要考虑几个“陷阱”:Kotlin 虽然非常接近 Java ,但在许多方面依然不同。因此,想要切换语言的开发者仍然面临着一定的学习曲线。因此,如果你决定将 Android 开发团队迁移到 Kotlin ,则需要对培训和时间进行额外的投资。 一些使用过 Kotlin 的开发者反映编译速度较慢,这是 Kotlin 的主要缺点之一。不过,在不同的测试环境下结果有所不同:在某些情况下,Kotlin 以编译速度击败 Java ,但有时它又比 Java 慢得多。 虽然 Kotlin 正在迅速成长为 Android 开发的首要语言,但目前仍然只有一个小型的开发者社区。这意味着用于学习该语言的资源有限,并且找出在应用开发过程中可能出现的问题的答案会比较困难。例如,在 StackOverflow 上搜索 Kotlin 仅有 3600 个左右的帖子,而 Java 有超过 1,000,000 个。由于 Kotlin 对大多数开发者来说仍然比较新,可能很难找到有经验的专业人士。

Kotlin VS Java:是时候切换语言了吗?

正如前面所说,这个问题很难回答。虽然 Kotlin 在某些方面显然优于 Java ,但仍远未完美。 如果你想尝试 Kotlin ,建议雇用一个专门的开发者,或让你的部分团队成员去尝试这种语言。即使它不会对你的应用的性能或其 UI 带来实际的结果,但也不会对其造成任何伤害。
继续阅读 »

 
Kotlin 语言说来也不是很新:是在 2011 年推出的,但火起来大家都知道是因为前几个月谷歌在 I / O 2017 上宣布它成为 Android 官方支持开发语言。自此之后,现在,Kotlin 开始出现在各个语言榜单之上,而且由于 JetBrains 和 Google 的企业支持基础,正迅速得到应用。

据 Kotlin 官方网站的信息,包括 Atlassian、Pivotal 、Uber、Pinterest、Evernote 等知名技术公司正在积极地将 Kotlin 用于 Android 应用开发。

如果你也正在考虑加入 Kotlin 的阵容,请确保已了解该技术的好处以及可能存在的陷阱。这里有一些关于 Kotlin 编程语言的见解,可供参考。

[使用Kotlin来开发Android,这些优缺点要考虑]

与已经发布 22 年的 Java 相比,Kotlin 有一些明显的改进:

提高团队的生产力

基于 Java 的 Kotlin 消除了其前身的过时和繁琐。语言紧凑、清晰、高效,语法简洁直观。因此,Kotlin 可以显着提高团队效率:编写和部署新代码所需的时间较少。这也有助于提高代码可维护性。

据 Keepsafe 的 Android 开发人员 A. J. Alt 所表示,将 “App Lock” 应用从 Java 转换为 Kotlin ,总代码量减少了 30% 。

与现有代码兼容

Kotlin 的优点之一是其 100% 的 Java 互操作性。该语言适用于 Java 本身,及所有相关工具和框架,提供了丰富的生态系统。这也使得可以选择逐渐迁移到 Kotlin ,或者在同一个项目中同时使用这两种语言。

可维护性

由 JetBrains 构建并支持,Kotlin 为许多 IDE(包括 Android Studio)提供了良好的支持。

更少的错误

通过更紧凑和更清晰的代码库,Kotlin 允许在生产中减少错误,生成更稳定的代码。编译器在编译时检测所有可能的错误,而不是运行时。这使得 Kotlin 成为比 Java 更安全的替代品。

可靠

不同于 Swift ,Kotlin 是一种更成熟的语言。在 2011 年推出后,在最终的 1.0 版本发布之前,经历了多个 Alfa 和 Beta 阶段。最新版本也与以前的版本反向兼容。

然而,在生产过程中使用 Kotlin 之前,仍需要考虑几个“陷阱”:Kotlin 虽然非常接近 Java ,但在许多方面依然不同。因此,想要切换语言的开发者仍然面临着一定的学习曲线。因此,如果你决定将 Android 开发团队迁移到 Kotlin ,则需要对培训和时间进行额外的投资。 一些使用过 Kotlin 的开发者反映编译速度较慢,这是 Kotlin 的主要缺点之一。不过,在不同的测试环境下结果有所不同:在某些情况下,Kotlin 以编译速度击败 Java ,但有时它又比 Java 慢得多。 虽然 Kotlin 正在迅速成长为 Android 开发的首要语言,但目前仍然只有一个小型的开发者社区。这意味着用于学习该语言的资源有限,并且找出在应用开发过程中可能出现的问题的答案会比较困难。例如,在 StackOverflow 上搜索 Kotlin 仅有 3600 个左右的帖子,而 Java 有超过 1,000,000 个。由于 Kotlin 对大多数开发者来说仍然比较新,可能很难找到有经验的专业人士。

Kotlin VS Java:是时候切换语言了吗?

正如前面所说,这个问题很难回答。虽然 Kotlin 在某些方面显然优于 Java ,但仍远未完美。 如果你想尝试 Kotlin ,建议雇用一个专门的开发者,或让你的部分团队成员去尝试这种语言。即使它不会对你的应用的性能或其 UI 带来实际的结果,但也不会对其造成任何伤害。 收起阅读 »

Kotlin学习系列(二)

IF表达式
if在kotlin可以当做表达式使用跟java的三元操作符类似:
var max =  if( a > b )  a else b
if分支可以使用代码块,最后一个表达式是返回值:
var max = if (a > b){
print(a)
a
}else{
print(b)
b
}
When表达式
kotlin使用when来替换switch语句,基本特性都跟switch差不多会对列出来的分支进行匹配满足条件的分支会被执行。when可以当做表达式或者语句
如果使用when当前表达式满足条件的分支会当做when的返回值。当when当做语句使用的时候会忽略所有分支的值。when的每个分支也可以是语句块最后一个表达式是这个语句块的值。

用做表达式:
    var matchValue = 2
var result = when(matchValue){
1 -> 1
2 -> 2
else ->3
}

println(result)
用于语句:
    matchValue = 3
when(matchValue) {
1 -> println(1)
2 -> println(2)
else -> println(3)
}
匹配多少值:
kotlin when(matchValue){ 1,2,3 -> println(matchValue) }
使用is与!is:
    var isInt = when(matchValue){
is Int -> println(matchValue)
else -> false
}
使用in与!in:
kotlin var valueIn = when(matchValue){ in 1..3 -> true else -> false }
当when没有提供一个值时它的分支是boolean表达式when会执行为真的分支:
    var valueIn = when(matchValue){
in 1..3 -> true
else -> false
}
for循环
通过任意提供的迭代器的对象循环(迭代器与java类似):
for (item in collection)
print(item)
遍历数组:
   var types = intArrayOf(1, 2, 3)
for(index in types.indices)
print(index.toString() + " ")

for((index, value ) in types.withIndex())
println("index: $index, value: $value")
while循环
跟平常的while使用一样:
    var index = 0
while(index < 10)
print(index++)

index = 0
do{
print(index)
}while (index++ < 10)
转载自:http://www.cnblogs.com/xwgblog/p/5289823.html
继续阅读 »
IF表达式
if在kotlin可以当做表达式使用跟java的三元操作符类似:
var max =  if( a > b )  a else b
if分支可以使用代码块,最后一个表达式是返回值:
var max = if (a > b){
print(a)
a
}else{
print(b)
b
}
When表达式
kotlin使用when来替换switch语句,基本特性都跟switch差不多会对列出来的分支进行匹配满足条件的分支会被执行。when可以当做表达式或者语句
如果使用when当前表达式满足条件的分支会当做when的返回值。当when当做语句使用的时候会忽略所有分支的值。when的每个分支也可以是语句块最后一个表达式是这个语句块的值。

用做表达式:
    var matchValue = 2
var result = when(matchValue){
1 -> 1
2 -> 2
else ->3
}

println(result)
用于语句:
    matchValue = 3
when(matchValue) {
1 -> println(1)
2 -> println(2)
else -> println(3)
}
匹配多少值:
kotlin when(matchValue){ 1,2,3 -> println(matchValue) }
使用is与!is:
    var isInt = when(matchValue){
is Int -> println(matchValue)
else -> false
}
使用in与!in:
kotlin var valueIn = when(matchValue){ in 1..3 -> true else -> false }
当when没有提供一个值时它的分支是boolean表达式when会执行为真的分支:
    var valueIn = when(matchValue){
in 1..3 -> true
else -> false
}
for循环
通过任意提供的迭代器的对象循环(迭代器与java类似):
for (item in collection)
print(item)
遍历数组:
   var types = intArrayOf(1, 2, 3)
for(index in types.indices)
print(index.toString() + " ")

for((index, value ) in types.withIndex())
println("index: $index, value: $value")
while循环
跟平常的while使用一样:
    var index = 0
while(index < 10)
print(index++)

index = 0
do{
print(index)
}while (index++ < 10)
转载自:http://www.cnblogs.com/xwgblog/p/5289823.html 收起阅读 »

Kotlin学习系列(一)

基本类型

在Kotlin中任何事物都是对象你可以在任何变量上调用相应的方法或属性。Kotlin的一些内置类型如下:
  • Number: 包含整形与浮点型
  • Character: 字符(Chat)
  • Boolean: 布尔值
  • String: 字符串
  • Array: 数组


在Kotlin内置的类型个人觉得更加像Java中的一些包装类,如果在学习之前将思维转换成Java包装类的思想我觉得学起来更容易理解一些。当然它们还与Java多少有些不同。

Number类型

Kotlin包含如下number类型:
  • Double
  • Float
  • Long
  • Int
  • Short
  • Byte


怎么样有没有感觉跟Java里面的java.lang.Double、java.lang.Long这些包装类差不多用起来也差不多。还有在Kotlin的数字常量可以用十进制、十六进制、指数形式小数、二进制但是没有八进制。Kotlin中是没有自动向上转型的。
//内置数据类型
var d: Double = 64.0
var i: Int = 32
var l: Long = 64
var f: Float = 32.0F
var b: Byte = 8
var s: Short = 16

//数字常量
i = 1 //十进制
i = 0x1 //十六进制
i = 01 //八进制不允许
i = 0b00000 //二进制
d = 1.2E10 //指数形式
f = 1.2E10F

//没有自动向上转换
l = i //Int不能自动转换成Long
d = f //同样Float也不能自动转换
不过上面说了Kotlin中任何事物都是对象那么我们可以调用相应的方法来显示转换。
var i: Int = 5;
var l: Long = i.toLong();
字符类型
字符类型在Kotlin中用Char来表示,它不能直接去应用一个number类型如var ch: Int = 'c'是错误的必需要显示的转换var ch: Int = 'c'.toInt()同样Char也支持转意字符\n、\b、\r等跟Java中的差不多。
 
数组
在Kotlin数组分为基本类型的数组和其他类型数据,基本数组类型是指数组中的元素类型都是基本数据类型如: Int、Long、Floa这些类型的数组在Kotlin中分别用IntArray、LongArray、FloatArray来表示可以通过Kotlin内置的方法来创建<*>ArrayOf(values)里面的*号代表具体的元素类型。
    var intArray: IntArray = intArrayOf(1, 3, 4);
var longArray: LongArray = longArrayOf(1L, 2L)
其他类型的数组可以使用Array通过传入大小与生成对象的方法来创建数组。
var str: Array<String> = Array(5, { index -> index.toString })
字符串
字符串用String表示同Java一样是不可变的同样内部也用字符组成,访问内部字符可以通过s和循环来遍历。
[i]var hello: String = "HelloWorld"

for(index: Int in 0..hello.length - 1){
println(hello[index])
}

for(ch in hello){
println(ch)
}[/i]
字符串可分为能够转意一些特殊字符的字符串和原始的字符串。
[i]    var text1: String = "Hello\tWorld"
var text2: String = """
Hello\bWorld
"""

println(text1)
println(text2)[/i]
在text1中\t会转间成一个制表符但在text2不但\b不会转意且任何内容都会照样输出。原始字符串类似XMl中的CDATA。字符串中可以使用模版,就像Java中的String.format的一样但在Kotlin中使用$号开始后面可以加变量名来替换内容。
[i]    var name: String = "Kotlin";
var greet: String = "Hi, $name";
println(greet)[/i]
学习总结

学习Kotlin时免不了要与Java比较但Kotlin更像类似Swift,看IOS同事写Swift后学习了Kotlin的基本类型后感觉太相似了。说实话还是比较喜欢Java这种强类型的语言也许是用了几年不太适应吧。既然开始了一定要坚持学下去不能落伍。本人水平有限可能免不了手滑一下如有错误烦请指出,会即时更改。

 
转载自:http://www.cnblogs.com/xwgblog/p/5245200.html
继续阅读 »
基本类型

在Kotlin中任何事物都是对象你可以在任何变量上调用相应的方法或属性。Kotlin的一些内置类型如下:
  • Number: 包含整形与浮点型
  • Character: 字符(Chat)
  • Boolean: 布尔值
  • String: 字符串
  • Array: 数组


在Kotlin内置的类型个人觉得更加像Java中的一些包装类,如果在学习之前将思维转换成Java包装类的思想我觉得学起来更容易理解一些。当然它们还与Java多少有些不同。

Number类型

Kotlin包含如下number类型:
  • Double
  • Float
  • Long
  • Int
  • Short
  • Byte


怎么样有没有感觉跟Java里面的java.lang.Double、java.lang.Long这些包装类差不多用起来也差不多。还有在Kotlin的数字常量可以用十进制、十六进制、指数形式小数、二进制但是没有八进制。Kotlin中是没有自动向上转型的。
//内置数据类型
var d: Double = 64.0
var i: Int = 32
var l: Long = 64
var f: Float = 32.0F
var b: Byte = 8
var s: Short = 16

//数字常量
i = 1 //十进制
i = 0x1 //十六进制
i = 01 //八进制不允许
i = 0b00000 //二进制
d = 1.2E10 //指数形式
f = 1.2E10F

//没有自动向上转换
l = i //Int不能自动转换成Long
d = f //同样Float也不能自动转换
不过上面说了Kotlin中任何事物都是对象那么我们可以调用相应的方法来显示转换。
var i: Int = 5;
var l: Long = i.toLong();
字符类型
字符类型在Kotlin中用Char来表示,它不能直接去应用一个number类型如var ch: Int = 'c'是错误的必需要显示的转换var ch: Int = 'c'.toInt()同样Char也支持转意字符\n、\b、\r等跟Java中的差不多。
 
数组
在Kotlin数组分为基本类型的数组和其他类型数据,基本数组类型是指数组中的元素类型都是基本数据类型如: Int、Long、Floa这些类型的数组在Kotlin中分别用IntArray、LongArray、FloatArray来表示可以通过Kotlin内置的方法来创建<*>ArrayOf(values)里面的*号代表具体的元素类型。
    var intArray: IntArray = intArrayOf(1, 3, 4);
var longArray: LongArray = longArrayOf(1L, 2L)
其他类型的数组可以使用Array通过传入大小与生成对象的方法来创建数组。
var str: Array<String> = Array(5, { index -> index.toString })
字符串
字符串用String表示同Java一样是不可变的同样内部也用字符组成,访问内部字符可以通过s和循环来遍历。
[i]var hello: String = "HelloWorld"

for(index: Int in 0..hello.length - 1){
println(hello[index])
}

for(ch in hello){
println(ch)
}[/i]
字符串可分为能够转意一些特殊字符的字符串和原始的字符串。
[i]    var text1: String = "Hello\tWorld"
var text2: String = """
Hello\bWorld
"""

println(text1)
println(text2)[/i]
在text1中\t会转间成一个制表符但在text2不但\b不会转意且任何内容都会照样输出。原始字符串类似XMl中的CDATA。字符串中可以使用模版,就像Java中的String.format的一样但在Kotlin中使用$号开始后面可以加变量名来替换内容。
[i]    var name: String = "Kotlin";
var greet: String = "Hi, $name";
println(greet)[/i]
学习总结

学习Kotlin时免不了要与Java比较但Kotlin更像类似Swift,看IOS同事写Swift后学习了Kotlin的基本类型后感觉太相似了。说实话还是比较喜欢Java这种强类型的语言也许是用了几年不太适应吧。既然开始了一定要坚持学下去不能落伍。本人水平有限可能免不了手滑一下如有错误烦请指出,会即时更改。

 
转载自:http://www.cnblogs.com/xwgblog/p/5245200.html 收起阅读 »

欢呼声热烈 谷歌宣布 Kotlin 成 Android 开发一级语言

谷歌I/O大会一开始就宣布了Android设备超过20亿部的好消息,会议推进至此,果然Android才是大会的压轴大戏么?

首先,今年夏末应该就可以收到Android O的推送,当然,国内用户就先别想了,除非你一直都用原生的。其次,有两个关键词需要注意,一是“Fluid Experience(流畅体验)”,二是“Vitals(核心功能)”。

地图、Netflix、浏览器中的视频等将支持安卓O画中画功能,随后还会有更多应用支持画中画,相当于另一种形态的多任务处理,这是Fluid Experience(流畅体验)的一部分。另外,通知部分也有升级,所谓“Notification Dots(通知点)”有点像是iOS App右上角的提示标,但是长按的话会显示更多信息。

Android O也带来了更加智能化的信息填充系统,未来不仅仅是Chrome中的表格信息,App中的信息也可以自动填充了。另外,新增的"智能文本选择”,可用于更加效率的复制和粘贴。最后,名为“TensorFlow Lite”的机器学习功能专用于手机,将会在之后的一段时间上线,具体功能并未详细提及。

Vitals(核心功能)部分,谷歌更强调电池续航、安全性、启动时间和稳定性。安全性方面,Google Play商店采用机器学习,每天都会扫描500亿次应用程序,告知你手机上的App已经经过扫描,让安全性更具可视化。

启动时间方面,谷歌给出的数据是,在Pixel上,Android O的启动时间是上代的一半。Android O的运行也会更加高效,保持闲置后台回收;太多的后台程序会消耗电池电量, Android O将提供智能节点措施。针对开发者,Play Console Dashboard可以告诉开发者他们的应用耗电、闪退情况;告知开发者有多少用户受到不良应用侵犯,协同开发者一起为用户提供更好的App体验。

然而并没有太多能和用户挂钩的功能性升级,至少大会上提到的这些内容,如果不算那一波更新的emoji,我们目前很难有什么实质性的感受。

最后,谷歌宣布,将Kotlin语言作为安卓开发的一级编程语言。Kotlin由JetBrains公司开发,与Java 100%互通,并具备诸多Java尚不支持的新特性。谷歌称还将与JetBrains公司合作,为Kotlin设立一个非盈利基金会。

JetBrains在2010年首次推出Kotlin编程语言,并在次年将之开源。下一版的Android Studio(3.0)也将提供支持。

稿源:网易科技、cnbeta
继续阅读 »
谷歌I/O大会一开始就宣布了Android设备超过20亿部的好消息,会议推进至此,果然Android才是大会的压轴大戏么?

首先,今年夏末应该就可以收到Android O的推送,当然,国内用户就先别想了,除非你一直都用原生的。其次,有两个关键词需要注意,一是“Fluid Experience(流畅体验)”,二是“Vitals(核心功能)”。

地图、Netflix、浏览器中的视频等将支持安卓O画中画功能,随后还会有更多应用支持画中画,相当于另一种形态的多任务处理,这是Fluid Experience(流畅体验)的一部分。另外,通知部分也有升级,所谓“Notification Dots(通知点)”有点像是iOS App右上角的提示标,但是长按的话会显示更多信息。

Android O也带来了更加智能化的信息填充系统,未来不仅仅是Chrome中的表格信息,App中的信息也可以自动填充了。另外,新增的"智能文本选择”,可用于更加效率的复制和粘贴。最后,名为“TensorFlow Lite”的机器学习功能专用于手机,将会在之后的一段时间上线,具体功能并未详细提及。

Vitals(核心功能)部分,谷歌更强调电池续航、安全性、启动时间和稳定性。安全性方面,Google Play商店采用机器学习,每天都会扫描500亿次应用程序,告知你手机上的App已经经过扫描,让安全性更具可视化。

启动时间方面,谷歌给出的数据是,在Pixel上,Android O的启动时间是上代的一半。Android O的运行也会更加高效,保持闲置后台回收;太多的后台程序会消耗电池电量, Android O将提供智能节点措施。针对开发者,Play Console Dashboard可以告诉开发者他们的应用耗电、闪退情况;告知开发者有多少用户受到不良应用侵犯,协同开发者一起为用户提供更好的App体验。

然而并没有太多能和用户挂钩的功能性升级,至少大会上提到的这些内容,如果不算那一波更新的emoji,我们目前很难有什么实质性的感受。

最后,谷歌宣布,将Kotlin语言作为安卓开发的一级编程语言。Kotlin由JetBrains公司开发,与Java 100%互通,并具备诸多Java尚不支持的新特性。谷歌称还将与JetBrains公司合作,为Kotlin设立一个非盈利基金会。

JetBrains在2010年首次推出Kotlin编程语言,并在次年将之开源。下一版的Android Studio(3.0)也将提供支持。

稿源:网易科技、cnbeta 收起阅读 »