效率的抉择 : 用 Kotlin 做 Android 开发 Bennyhuo
个人简介 霍丙乾,Bennyhuo, 就职于腾讯地图 Github: https://github.com/enbandari Kotlin 微信公众号 Kotlin 社区 :https://kotliner.cn Kotlin 博客 :https://blog.kotliner.cn
Kotlin 简介
Kotlin 的基本情况
Kotlin 的基本情况
Kotlin 的基本情况 Andrey Breslav Hadi Hariri
Kotlin 的基本情况
Kotlin 的基本情况
Kotlin 的基本情况 100% 兼容 Java
Kotlin 的基本情况
Kotlin 的基本情况
Kotlin 的基本情况 Android 官方开发语言
Kotlin 的基本情况
Kotlin 的基本情况
Kotlin 的基本情况 正式支持 JavaScript Target
Kotlin 的基本情况
Kotlin 的基本情况
Kotlin 的基本情况 Native Target 预览版 0.4
Kotlin 的基本情况
Kotlin 的基本情况
你是如何认识 Kotlin 的? 其他 15% 同学朋友 8% 缘分 13% Google IO 大会 42% JetBrains 22%
你从事何种职业? 其他 13% 服务端研发 14% 学生 17% Android 研发 56%
你或者你所在的项目如何使用 Kotlin 的? 其他 2% 不敢用 16% 全部使用 Kotlin 17% Demo 开发 44% 小范围线上 21%
你觉得 Kotlin 最吸引你的特性是什么? 没有分号 5% 属性代理 3% DSL 4% 协程 4% 数据类型 10% Lambda/ 高阶函数 25% 空安全类型 18% 跨平台一统江湖 17% 扩展方法 14%
你所在的公司人数? 10000 以上 9% 1000-10000 12% 50 人以下 41% 200-1000 19% 50-200 19%
你的年龄范围? 85 后 17% 其他 1% 80 后 8% 00 后 2% 95 后 25% 90 后 47%
Kotlin 高端大气上档次
相关资料
Android developer 地址 : https://developer.android.com/kotlin/index.html
Kotlin 官网 地址 : http://kotlinlang.org/
Kotlin 官网 ( 中文版 ) 地址 :https://www.kotlincn.net/
Kotlin 论坛 地址 :https://discuss.kotlinlang.org/
Kotlin 论坛 ( 中文版 ) 地址 :https://kotliner.cn/
Kotlin 博客 地址 :https://blog.jetbrains.com/kotlin
Kotlin 博客 ( 中文版 ) 地址 :https://blog.kotliner.cn/
Kotlin 公众号 微信公众号 :Kotlin
Kotlin 教学视频 O'Reilly Introduction to Kotlin Programming:http://hadihariri.com/2016/11/01/oreillykotlin-course/ O'Reilly Advanced Kotlin Programming:http://hadihariri.com/2016/11/01/oreilly-kotlincourse/ Github Kotlin 入门到 放弃 :https://github.com/enbandari/kotlin-tutorials 慕课网 Kotlin 入门到进阶 :http://coding.imooc.com/class/108.html
培训目标 认识 Kotlin 了解 Kotlin 的基本语法 熟悉 Kotlin 特性的一些应用场景 最后把培训的内容都忘了
下面开始讲代码
Kotlin 版本 Jvm/Js 1.0 2016.2 1.1 2017 1.2 即将面世
简洁, 就要少写废话
高效, 就要少犯错误
创建工程
创建工程
配置工程 buildscript { ext.kotlin_version = '1.1.51' repositories { google() jcenter() dependencies { classpath 'com.android.tools.build:gradle:3.0.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files
配置工程 buildscript { ext.kotlin_version = '1.1.51' repositories { google() jcenter() dependencies { classpath 'com.android.tools.build:gradle:3.0.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files
配置工程 apply plugin: 'com.android.application' apply plugin: 'kotlin-android' android {... dependencies { implementation filetree(dir: 'libs', include: ['*.jar']) implementation"org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version...
配置工程 apply plugin: 'com.android.application' apply plugin: 'kotlin-android' android {... dependencies { implementation filetree(dir: 'libs', include: ['*.jar']) implementation"org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version...
如何定义变量 int anint = 2;
如何定义变量 val anint: Int = 2
如何定义变量 val anint: Int = 2
如何定义变量 val anint = 2
如何定义变量 val anint = 2 anint = 3
如何定义变量 val anint = 2 anint = 3
如何定义变量 var anint = 2 anint = 3
如何定义变量 val anint = 2 final int anint = 2; var anint = 2 int anint = 2; Kotlin Java
如何定义函数 void hello(int anint){ System.out.println(anInt);
如何定义函数 fun hello(anint: Int): Unit{ println(anint)
如何定义函数 fun hello(anint: Int): Unit{ println(anint)
如何定义函数 fun hello(anint: Int) { println(anint)
如何定义函数 fun hello(anint: Int) { println(anint)
如何定义函数 fun hello(anint: Int) { println(anint)
如何定义函数 fun hello(anint: Int) { println(anint)
如何定义函数 fun hello(anint: Int) { println(anint)
如何定义函数 fun hello(anint: Int): Unit{ println(anint)
如何定义数组 int[] intarray = new int[5]; int[] anotherintarray = {1,2, 3,4,5;
如何定义数组 val intarray = IntArray(5) val anotherintarray = intarrayof(1, 2, 3, 4, 5)
如何定义数组 int[] intarray = new int[5];
如何定义数组 int[] intarray = new int[5]; for (int i = 0; i < intarray.length; i++) { intarray[i] = i;
如何定义数组 val intarray = IntArray(5){ it
如何定义数组 val intarray = IntArray(5){ it * 2
如何操作数组 intarray[1] = 2; int element3 = intarray[3] ;
如何操作数组 intarray[1] = 2 val element3 = intarray[3]
运算符 intarray[1] = 2 intarray.set(1, 2) val element3 = intarray[3] val element3 = intarray.get(3) 如果是 List Set 呢?
运算符 class 逗你玩 { operator fun set(int: Int, value: Any){ operator fun get(int: Int) = Unit
运算符 class 逗你玩 { operator fun set(int: Int, value: Any){ operator fun get(int: Int) = Unit val 逗你玩的实例 = 逗你玩 () 逗你玩的实例 [2] = 3 val x = 逗你玩的实例 [1]
WARNING 请不要用中文编程, 不然你可能找不到工作
数组的类型 基本类型的数组 ShortArray/IntArray/LongArray/FloatArray/DoubleArray/CharArray/Bool eanarray 其他类型数组 val stringarray = Array(5){ it.tostring() // Array<String> val anotherstringarray = arrayof("hello", "world") val strings = arrayofnulls<string>(5)
数组的类型 基本类型的数组 ShortArray/IntArray/LongArray/FloatArray/DoubleArray/CharArray/Bool eanarray 其他类型数组 val stringarray = Array(5){ it.tostring() // Array<String> val anotherstringarray = arrayof("hello", "world") val strings = arrayofnulls<string>(5)
数组的类型 基本类型的数组 ShortArray/IntArray/LongArray/FloatArray/DoubleArray/CharArray/Bool eanarray 其他类型数组 val stringarray = Array(5){ it.tostring() // Array<String> val anotherstringarray = arrayof("hello", "world") val strings = arrayofnulls<string>(5)
如何定义类 interface AnInterface{ class SuperClass{ public SuperClass() { class SubClass extends SuperClass implements AnInterface{ public SubClass() { super();
如何定义类 interface AnInterface class SuperClass(){ class SubClass : SuperClass(), AnInterface{
如何定义类 interface AnInterface class SuperClass{ class SubClass : SuperClass(), AnInterface{
如何定义类 interface AnInterface class SuperClass class SubClass : SuperClass(), AnInterface
如何定义类 interface AnInterface class SuperClass class SubClass : SuperClass(), AnInterface
如何定义类 interface AnInterface open class SuperClass class SubClass : SuperClass(), AnInterface
如何定义类 interface AnInterface open class SuperClass class SubClass : SuperClass(), AnInterface
如何实例化类 SubClass subclass = new SubClass();
如何实例化类 val subclass = new SubClass()
如何实例化类 val subclass = new SubClass()
如何实例化类 val subclass = SubClass()
如何实例化类 var subclass = SubClass()
构造方法 interface AnInterface open class SuperClass class SubClass : SuperClass(), AnInterface
构造方法 interface AnInterface open class SuperClass( aparam: Int ) class SubClass : SuperClass( 10 ), AnInterface
构造方法 interface AnInterface open class SuperClass(aParam: Int) { init { println(aparam) val aproperty = aparam class SubClass : SuperClass(10), AnInterface
构造方法 interface AnInterface open class SuperClass(aParam: Int) { init { println(aparam) val aproperty = aparam class SubClass ( aparamforsuper: Int ) : SuperClass( aparamforsuper ), AnInterface
构造方法 class SubClass( val apropertyinsub: String, aparamforsuper: Int ) : SuperClass( aparamforsuper ), AnInterface
构造方法 class SubClass( val apropertyinsub: String, aparamforsuper: Int ) : SuperClass( aparamforsuper ), AnInterface val subclass = SubClass("Hello", 10) subclass.
构造方法 public class Call { private String callid;
构造方法 public class Call { private String callid; public Call(String callid) { this.callid = callid;
构造方法 public class Call { private String callid; public Call(){ // 稍后再初始化 callid public Call(String callid) { this.callid = callid;
构造方法 public class Call { private final String callid; public Call(String callid) { this.callid = callid;
构造方法 class Call(val callid: String)
构造方法 class Call(val callid: String){ constructor()
构造方法 class Call(val callid: String){ constructor()
构造方法 class Call(val callid: String){ constructor(): this()
构造方法 public ViewGroup(Context context) { this(context, null); public ViewGroup(Context context, AttributeSet attrs) { this(context, attrs, 0); public ViewGroup(Context context, AttributeSet attrs, int defstyleattr) { this(context, attrs, defstyleattr, 0); public ViewGroup(Context context, AttributeSet attrs, int defstyleattr, int defstyleres) { super(context, attrs, defstyleattr, defstyleres);...
构造方法 public SomeViewGroup(Context context) { super(context); init(); public SomeViewGroup(Context context, AttributeSet attrs) { super(context, attrs); init();
构造方法 public SomeViewGroup(Context context) { super(context); init(); initdata(); public SomeViewGroup(Context context, AttributeSet attrs) { super(context, attrs); init();
构造方法 public SomeViewGroup(Context context) { super(context); init(); initdata(); public SomeViewGroup(Context context, AttributeSet attrs) { super(context, attrs); init(); initdata();
构造方法 public SomeViewGroup(Context context) { super(context); init(); initdata(); public SomeViewGroup(Context context, AttributeSet attrs) { super(context, attrs); init(); initdata();
方法重载 public interface List<E> extends Collection<E> {... public E remove(int location); public boolean remove(object object);...
方法重载 public interface List<E> extends Collection<E> {... public E remove(int location); public boolean remove(object object);... List<Integer> integers = new ArrayList<>();... integers.remove(2);
方法重载 public interface List<E> extends Collection<E> {... public E remove(int location); public boolean remove(object object);... val integers = ArrayList<Int>()... integers.removeat(2)
方法重载 public interface List<E> extends Collection<E> {... public E remove(int location); public boolean remove(object object);... val integers = ArrayList<Int>()... integers.removeat(2)
默认参数 class SomeViewGroup(context: Context, attrs: AttributeSet?, defstyleattr: Int, defstyleres: Int) : ViewGroup(context, attrs, defstyleattr, defstyleres) { init {...
默认参数 class SomeViewGroup(context: Context, attrs: AttributeSet? = null, defstyleattr: Int = 0, defstyleres: Int = 0) : ViewGroup(context, attrs, defstyleattr, defstyleres) { init {...
覆写父类成员 @Override protected void onresume() { super.onresume(); tencentmapview.onresume(); @Override protected void onpause() { super.onpause(); tencentmapview.onpause();
覆写父类成员 public class MyMapView extends MapView {... public void onresume() { dosomethingonresume(); @Override public void onpause() { super.onpause(); dosomethingonpause();...
覆写父类成员 class MyMapView(context: Context) : MapView(context) { fun onresume() { dosomethingonresume() override fun onpause() { super.onpause() dosomethingonpause()
覆写父类成员 class MyMapView(context: Context) : MapView(context) { override fun onresume() { dosomethingonresume() override fun onpause() { super.onpause() dosomethingonpause()
属性代理 public class Link { private double length = -1; private List<LatLng> points;...
属性代理 public void update(latlng latlng){... if(length == -1){ length = resolvelength();... private double resolvelength(){ return...;
属性代理 public void update(latlng latlng){... double length = getlength();... public double getlength(){ if(length == -1){ length = resolvelength(); return length; private double resolvelength(){ return...;
属性代理 private val length by lazy { resolvelength() private fun resolvelength(): Double { return...
属性代理 private val length by lazy {...
属性代理 private val length by lazy( SYNCHRONIZED ) {...
属性代理 enum class LazyThreadSafetyMode { SYNCHRONIZED, PUBLICATION, NONE,
属性代理 inline operator fun <T> Lazy<T>.getValue( thisref: Any?, property: KProperty<*> ): T = value
属性代理 private var _value: Any? = UNINITIALIZED_VALUE override val value: T get() { if (_value === UNINITIALIZED_VALUE) { _value = initializer!!() initializer = null return _value as T
属性代理 private var _value: Any? = UNINITIALIZED_VALUE override val value: T get() { if (_value === UNINITIALIZED_VALUE) { _value = initializer!!() initializer = null return _value as T private val length by lazy {...
属性代理 public interface ReadWriteProperty<in R, T> { public operator fun getvalue(thisref: R, property: KProperty<*>): T public operator fun setvalue(thisref: R, property: KProperty<*>, value: T)
属性代理 class PropertiesDelegate <T> (val path: String): ReadWriteProperty <Any, T> { val properties: Properties by lazy {... // 读属性 override operator fun getvalue(thisref: Any, property: KProperty<*>): T { val value = properties[property.name] val classoft = property.returntype.classifier as KClass<*> return if (Number::class.isSuperclassOf(classOfT)) {... // 如果是数值需要做一些转换 else { value as T override operator fun setvalue(thisref: Any, property: KProperty<*>, value: T) { properties[property.name] = value... // 存属性
属性代理 class PropertiesDelegate (val path: String) { val properties: Properties by lazy {... // 读属性 operator fun <T> getvalue(thisref: Any, property: KProperty<*>): T { val value = properties[property.name] val classoft = property.returntype.classifier as KClass<*> return if (Number::class.isSuperclassOf(classOfT)) {... // 如果是数值需要做一些转换 else { value as T operator fun <T> setvalue(thisref: Any, property: KProperty<*>, value: T) { properties[property.name] = value... // 存属性
属性代理 abstract class AbsProperties(path: String) { protected val prop = PropertiesDelegate(path)
属性代理 abstract class AbsProperties(path: String) { protected val prop = PropertiesDelegate(path) object MetaInfo: AbsProperties("/meta.properties"){ val version: String by prop val author: String by prop val name: String by prop val desc: String by prop
属性代理 object MetaInfo: AbsProperties("/meta.properties"){ val version: String by prop val author: String by prop val name: String by prop val desc: String by prop version=1.0-snapshot author=bennyhuo@kotliner.cn name=qcloudimageuploader desc= 方便地批量上传指定目录的图片到腾讯云的免费 50G 图床
属性代理 link: <https://api.github.com/user/repos?page=2>; rel="next", <https://api.github.com/user/repos?page=5>; rel="last"
属性代理 link: <https://api.github.com/user/repos?page=2>; rel="next", <https://api.github.com/user/repos?page=5>; rel="last"
属性代理 map["next"] = "https://api.github.com/user/repos?page=2" map["last"] = "https://api.github.com/user/repos?page=5"
属性代理 map["next"] = "https://api.github.com/user/repos?page=2" map["last"] = "https://api.github.com/user/repos?page=5" map["first"] = "https://api.github.com/user/repos?page=1" map["prev"] = "https://api.github.com/user/repos?page=1"
属性代理 class GitHubPaging{ val islast: Boolean =? val isfirst: Boolean =? val hasprev: Boolean =? val hasnext: Boolean =? operator fun get(key: String): String?{ return?
属性代理 class GitHubPaging{ val first: String? =? val last: String? =? val next: String? =? val prev: String? =? val islast: Boolean =? val isfirst: Boolean =? val hasprev: Boolean =? val hasnext: Boolean =?
属性代理 class GitHubPaging{ val first by map... val isfirst get() = first == null... 参考 Kotlin 公众号文章 : 用 Map 为你的属性做代理
属性代理 object Settings { var lastpage by pref(0) var daynightmode by pref(false) var enablepush by pref(false) 参考 Kotlin 公众号文章 : 用 Map 为你的属性做代理
接口代理 interface PageManager { fun showpage(clazz: KClass<out Page>) fun goback()
接口代理 class PageManagerImpl: PageManager{ override fun showpage(clazz: KClass<out Page>) {... override fun goback() {... override fun dismiss() {..
接口代理 abstract class AbstractPage(val pagemanager: PageManager) : Page, PageManager { override fun showpage(clazz: KClass<out Page>) { pagemanager.showpage(clazz) override fun goback() { pagemanager.goback() override fun dismiss() { pagemanager.dismiss()
接口代理 abstract class AbstractPage(val pagemanager: PageManager) : Page, PageManager by pagemanager{
接口代理 abstract class AbstractPage(val pagemanager: PageManager) : Page, PageManager by pagemanager
扩展成员 inline operator fun <T> Lazy<T>.getValue( thisref: Any?, property: KProperty<*> ): T = value
扩展成员 inline operator fun <T> Lazy<T>.getValue( thisref: Any?, property: KProperty<*> ): T = value
扩展成员 inline operator fun <T> Lazy<T>.getValue( thisref: Any?, property: KProperty<*> ): T = value
扩展成员 inline operator fun <T> Lazy<T>.getValue( thisref: Any?, property: KProperty<*> ): T = value
扩展成员 public class DensityUtil { /** * 根据手机的分辨率从 dp 的单位转成为 px( 像素 ) */ public static int dip2px(float dpvalue) { final float scale = ContextHolder.getInstance().getContext().getResources().getDisplayMetrics().density; return (int) (dpvalue * scale + 0.5f); /** * 根据手机的分辨率从 px( 像素 ) 的单位转成为 dp */ public static int px2dip(float pxvalue) { final float scale = ContextHolder.getInstance().getContext().getResources().getDisplayMetrics().density; return (int) (pxvalue / scale + 0.5f);
扩展成员 //returns dip(dp) dimension value in pixels fun Context.dip(value: Int): Int = (value * resources.displaymetrics.density).toint() fun Context.dip(value: Float): Int = (value * resources.displaymetrics.density).toint() //return sp dimension value in pixels fun Context.sp(value: Int): Int = (value * resources.displaymetrics.scaleddensity).toint() fun Context.sp(value: Float): Int = (value * resources.displaymetrics.scaleddensity).toint() //converts px value into dip or sp fun Context.px2dip(px: Int): Float = px.tofloat() / resources.displaymetrics.density fun Context.px2sp(px: Int): Float = px.tofloat() / resources.displaymetrics.scaleddensity
扩展成员 listview.scrollx = dip(2) paint.strokewidth = dip(2).tofloat() paint.textsize = sp(12).tofloat()
扩展成员 logger.error("*************************") logger.error("++++++++++++++++")
扩展成员 fun String.times(other: Int): String{ return (1..other).fold(StringBuilder()){ acc, i -> acc.append(this) acc.tostring()
扩展成员 logger.error("*************************") logger.error("++++++++++++++++")
扩展成员 logger.error("*".times(8) ) logger.error("+".times(8) )
扩展成员 fun String.times(other: Int): String{ return (1..other).fold(StringBuilder()){ acc, i -> acc.append(this) acc.tostring()
扩展成员 operator fun String.times(other: Int): String{ return (1..other).fold(StringBuilder()){ acc, i -> acc.append(this) acc.tostring()
扩展成员 logger.error("*".times(8) ) logger.error("+".times(8) )
扩展成员 logger.error("*" * 8 ) logger.error("+" * 8 )
运算符 a + b a - b a.plus(b) a.minus(b) a * b a / b a.times(b) a.div(b)
扩展成员 String formatteddate = new SimpleDateFormat("yyyy-MM-dd").format(new Date()); Java
扩展成员 new Date().format("yyyy-MM-dd") Groovy
扩展成员 val formatteddate = SimpleDateFormat("yyyy-MM-dd").format(Date()) Kotlin
扩展成员 fun Date.format(format: String) : String{ return SimpleDateFormat(format).format(this)
扩展成员 fun Date.format(format: String) : String = SimpleDateFormat(format).format(this)
扩展成员 fun Date.format(format: String) = SimpleDateFormat(format).format(this)
扩展成员 val formatteddate = SimpleDateFormat("yyyy-MM-dd").format(Date()) Kotlin
扩展成员 val formatteddate = Date().format("yyyy-MM-dd")
如何比较对象 String astring = "Hello Kotliner"; String anotherstring = new String("Hello Kotliner"); System.out.println(aString == anotherstring); System.out.println(aString.equals(anotherString)); System.out.println(aString == anotherstring.intern()); System.out.println(aString.equals(anotherString.intern()));
如何比较对象 String astring = "Hello Kotliner"; String anotherstring = new String("Hello Kotliner"); System.out.println(aString == anotherstring); System.out.println(aString.equals(anotherString)); System.out.println(aString == anotherstring.intern()); System.out.println(aString.equals(anotherString.intern()));
如何比较对象 val astring = "Hello Kotliner" val anotherstring = String("Hello Kotliner")
如何比较对象 val astring = "Hello Kotliner" val anotherstring = String("Hello Kotliner")
如何比较对象 val astring = "Hello Kotliner" val anotherstring = String("Hello Kotliner".toByteArray()) println(astring === anotherstring) println(astring == anotherstring) println(astring === anotherstring.intern()) println(astring == anotherstring.intern())
如何比较对象 val astring = "Hello Kotliner" val anotherstring = String("Hello Kotliner".toByteArray()) println(astring === anotherstring) println(astring == anotherstring) println(astring === anotherstring.intern()) println(astring == anotherstring.intern())
如何比较对象 val astring = "Hello Kotliner" val anotherstring = String("Hello Kotliner".toByteArray()) println(astring === anotherstring) println(astring == anotherstring) println(astring === anotherstring.intern()) println(astring == anotherstring.intern())
如何比较对象 val astring = "Hello Kotliner" val anotherstring = String("Hello Kotliner".toByteArray()) println(astring === anotherstring) println(astring == anotherstring) println(astring === anotherstring.intern()) println(astring == anotherstring.intern())
如何比较对象 val astring = "Hello Kotliner" val anotherstring = String("Hello Kotliner".toByteArray()) println(astring === anotherstring) println(astring.equals(anotherstring)) println(astring === anotherstring.intern()) println(astring.equals(anotherstring.intern()))
如何比较对象 a == b a.equals(b) a === b a == b Kotlin Java
如何比较对象 var anint =... var anotherint =... if(anint < anotherint){ println("anint < anotherint") else { println("anint > anotherint")
如何比较对象 var anint =... var anotherint =... if(anint.compareto( anotherint ) < 0){ println("anint < anotherint") else { println("anint > anotherint")
运算符 a == b a.equals(b) a < b a.compareto(b) < 0 a > b a.compareto(b) > 0 a >= b 和 a <= b 呢?
数据类 public class Link { private String id; private double length; private String name; private String attributes; public String getid() { return id; public void setid(string id) { this.id = id;... // Getters/Setters