Kotlin中文文档

Kotlin中文文档

Kotlin中文文档
在线调试

在线调试

Kotlin在线调试工具
开发工具

开发工具

Kotlin开发工具IntelliJ IDEA
技术问答

技术问答

Kotlin技术问答与交流专区

Kotlin的密封(Sealed)类:超强的枚举(KAD 28)

作者:Antonio Leiva
时间:Jun 27, 2017
原文链接:https://antonioleiva.com/sealed-classes-kotlin/

 
 
Kotlin的封装类是Java中没有的新概念,并为此开辟了另一片可能性新的世界。
 
密封类允许你表达约束层次结构,其中对象只能是给定类型之一。
 
 
也就是说,我们有一个具有特定数量的子类的类。最后,我们得到的结论是非常类似枚举的概念。所不同的是,在枚举中,我们每个类型只有一个对象;而在密封类中,同一个类可以拥有几个对象。
 
 
这种差异允许密封类的对象可以保持状态。这给我们带来一些的优势(稍后会看到),它也为函数性概念敞开大门。
 
 
怎样使用密封类
 
 
 
实际上,实现密封类很简单。让我们来看一组能够应用于整数操作的例子。
 
 
实现情况如下:
 

1 sealed class Operation {
2 class Add(val value: Int) : Operation()
3 class Substract(val value: Int) : Operation()
4 class Multiply(val value: Int) : Operation()
5 class Divide(val value: Int) : Operation()
6 }

 
 
我们创建一个名为Operation的密封类,它包含四种操作:加法,减法,乘法和除法。
 
 
这一好处是,现在when表达式要求我们为所有可能的类型提供分支:
 

1 fun execute(x: Int, op: Operation) = when (op) {
2 is Operation.Add -> x + op.value
3 is Operation.Substract -> x - op.value
4 is Operation.Multiply -> x * op.value
5 is Operation.Divide -> x / op.value
6 }

 
 
如果你离开任何一个子类,when会抱怨其不会编译。如果你实现它们,你不需要else语句。通常,由于我们确信我们对所有人都做正确的事情,不推荐这样做。
 
 
因为它会在编译时失败,并且不会运行,如果你决定添加新操作,这样做也非常好。现添加一对操作,增量和减量:
 

1 sealed class Operation {
2 ...
3 object Increment : Operation()
4 object Decrement : Operation()
5 }

 
 
现在,你会看到编译器警告你,存在一个问题。只需为这些新操作添加分支:
 

1 fun execute(x: Int, op: Operation) = when (op) {
2 ...
3 Operation.Increment -> x + 1
4 Operation.Decrement -> x - 1
5 }

 
 
你可能已经注意到我做了不同的事情。我使用对象而不是类。这是因为如果一个子类不保持状态,它只能是一个对象。你为该类创建的所有实例将完全相同,它们不能有不同的状态。
 
那么,在when表达式中,对那些情况你可以摆脱is。在这里,因为只有一个实例,你只能比较对象,你不需要检查对象的类型。如果为那些,你也可以保留is,它也能工作。
 
 
如果你仔细考虑一下,所有子类都是对象的密封类与枚举相同。
 
 
将副作用移到单点上
 
 
 
函数编程的副作用是一个非常通用概念。函数编程在很大程度上依赖于给定的功能,相同的参数将返回相同的结果。
 
 
任何修改状态都可能会破坏这一假设。但是任何程序都需要更改状态,与输入/输出元素进行通讯等。因此,重要的是如何在我们的代码中发现这些操作,并很容易隔离到特定地方。
 
例如,在Android视图上实现的任何操作都被视为副作用,因为视图的状态修改,而函数不知道。
 
我们可以创建一个密封类,使我们能够对视图进行操作。基于这个概念,以前的例子:
 

1 sealed class UiOp {
2 object Show: UiOp()
3 object Hide: UiOp()
4 class TranslateX(val px: Float): UiOp()
5 class TranslateY(val px: Float): UiOp()
6 }
7
8 fun execute(view: View, op: UiOp) = when (op) {
9 UiOp.Show -> view.visibility = View.VISIBLE
10 UiOp.Hide -> view.visibility = View.GONE
11 is UiOp.TranslateX -> view.translationX = op.px
12 is UiOp.TranslateY -> view.translationY = op.px
13 }

 
 
记住:因为我们不需要不同的实例,没有状态的操作就可以是对象。
 
 
现在,你可以创建一个Ui对象,汇集要在视图上做的所有接口操作,直到我们需要时,才执行它。
 
 
我们将描述我们想要做什么,然后我们可以创建一个执行它们的组件:
 

1 class Ui(val uiOps: List = emptyList()) {
2 operator fun plus(uiOp: UiOp) = Ui(uiOps + uiOp)
3 }

 
 
Ui类存储操作列表,并指定一个累加和运算符,这将有助于使所有内容更清晰,更易于阅读。现在我们可以指定要执行的操作列表:
 

1 val ui = Ui() +
2 UiOp.Show +
3 UiOp.TranslateX(20f) +
4 UiOp.TranslateY(40f) +
5 UiOp.Hide
6
7 run(view, ui)

 
 
 
然后运行它。这里我只是使用一个run函数,但如果需要,这可以是一个完整的类。

1 fun run(view: View, ui: Ui) {
2 ui.uiOps.forEach { execute(view, it) }
3 }

 
 
想象一下这些,现在你所做的一切都是按顺序运行的,但是这可能会很复杂。
 
 
此run函数可以传递给另一个函数或类,并且那些操作的运行方式将是完全可互换的。记住你可以将函数作为参数传递。
 
 
结论
 
 
密封类的概念非常简单,但是如果您之前没有使用函数式编程,则需要一些使用新概念的基础。
 
 
我必须说,由于我在函数式编程方面的知识限制,我还没有最大限度的使用密封类。
 
 
如果您像我一样热衷于此,我建议你查看以前的文章,您可以在其中了解更多有关Kotlin的信息,或者在本书中了解如何使用Kotlin从头开始创建一个完整的Android应用程序。
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
val ui = Ui() +
        UiOp.Show +
       
UiOp.TranslateX(20f) +
       
UiOp.TranslateY(40f) +
        UiOp.Hide
 
run(view,
ui)转载自:https://www.cnblogs.com/figozhg/p/7107053.html
继续阅读 »
作者:Antonio Leiva
时间:Jun 27, 2017
原文链接:https://antonioleiva.com/sealed-classes-kotlin/

 
 
Kotlin的封装类是Java中没有的新概念,并为此开辟了另一片可能性新的世界。
 
密封类允许你表达约束层次结构,其中对象只能是给定类型之一。
 
 
也就是说,我们有一个具有特定数量的子类的类。最后,我们得到的结论是非常类似枚举的概念。所不同的是,在枚举中,我们每个类型只有一个对象;而在密封类中,同一个类可以拥有几个对象。
 
 
这种差异允许密封类的对象可以保持状态。这给我们带来一些的优势(稍后会看到),它也为函数性概念敞开大门。
 
 
怎样使用密封类
 
 
 
实际上,实现密封类很简单。让我们来看一组能够应用于整数操作的例子。
 
 
实现情况如下:
 

1 sealed class Operation {
2 class Add(val value: Int) : Operation()
3 class Substract(val value: Int) : Operation()
4 class Multiply(val value: Int) : Operation()
5 class Divide(val value: Int) : Operation()
6 }

 
 
我们创建一个名为Operation的密封类,它包含四种操作:加法,减法,乘法和除法。
 
 
这一好处是,现在when表达式要求我们为所有可能的类型提供分支:
 

1 fun execute(x: Int, op: Operation) = when (op) {
2 is Operation.Add -> x + op.value
3 is Operation.Substract -> x - op.value
4 is Operation.Multiply -> x * op.value
5 is Operation.Divide -> x / op.value
6 }

 
 
如果你离开任何一个子类,when会抱怨其不会编译。如果你实现它们,你不需要else语句。通常,由于我们确信我们对所有人都做正确的事情,不推荐这样做。
 
 
因为它会在编译时失败,并且不会运行,如果你决定添加新操作,这样做也非常好。现添加一对操作,增量和减量:
 

1 sealed class Operation {
2 ...
3 object Increment : Operation()
4 object Decrement : Operation()
5 }

 
 
现在,你会看到编译器警告你,存在一个问题。只需为这些新操作添加分支:
 

1 fun execute(x: Int, op: Operation) = when (op) {
2 ...
3 Operation.Increment -> x + 1
4 Operation.Decrement -> x - 1
5 }

 
 
你可能已经注意到我做了不同的事情。我使用对象而不是类。这是因为如果一个子类不保持状态,它只能是一个对象。你为该类创建的所有实例将完全相同,它们不能有不同的状态。
 
那么,在when表达式中,对那些情况你可以摆脱is。在这里,因为只有一个实例,你只能比较对象,你不需要检查对象的类型。如果为那些,你也可以保留is,它也能工作。
 
 
如果你仔细考虑一下,所有子类都是对象的密封类与枚举相同。
 
 
将副作用移到单点上
 
 
 
函数编程的副作用是一个非常通用概念。函数编程在很大程度上依赖于给定的功能,相同的参数将返回相同的结果。
 
 
任何修改状态都可能会破坏这一假设。但是任何程序都需要更改状态,与输入/输出元素进行通讯等。因此,重要的是如何在我们的代码中发现这些操作,并很容易隔离到特定地方。
 
例如,在Android视图上实现的任何操作都被视为副作用,因为视图的状态修改,而函数不知道。
 
我们可以创建一个密封类,使我们能够对视图进行操作。基于这个概念,以前的例子:
 

1 sealed class UiOp {
2 object Show: UiOp()
3 object Hide: UiOp()
4 class TranslateX(val px: Float): UiOp()
5 class TranslateY(val px: Float): UiOp()
6 }
7
8 fun execute(view: View, op: UiOp) = when (op) {
9 UiOp.Show -> view.visibility = View.VISIBLE
10 UiOp.Hide -> view.visibility = View.GONE
11 is UiOp.TranslateX -> view.translationX = op.px
12 is UiOp.TranslateY -> view.translationY = op.px
13 }

 
 
记住:因为我们不需要不同的实例,没有状态的操作就可以是对象。
 
 
现在,你可以创建一个Ui对象,汇集要在视图上做的所有接口操作,直到我们需要时,才执行它。
 
 
我们将描述我们想要做什么,然后我们可以创建一个执行它们的组件:
 

1 class Ui(val uiOps: List = emptyList()) {
2 operator fun plus(uiOp: UiOp) = Ui(uiOps + uiOp)
3 }

 
 
Ui类存储操作列表,并指定一个累加和运算符,这将有助于使所有内容更清晰,更易于阅读。现在我们可以指定要执行的操作列表:
 

1 val ui = Ui() +
2 UiOp.Show +
3 UiOp.TranslateX(20f) +
4 UiOp.TranslateY(40f) +
5 UiOp.Hide
6
7 run(view, ui)

 
 
 
然后运行它。这里我只是使用一个run函数,但如果需要,这可以是一个完整的类。

1 fun run(view: View, ui: Ui) {
2 ui.uiOps.forEach { execute(view, it) }
3 }

 
 
想象一下这些,现在你所做的一切都是按顺序运行的,但是这可能会很复杂。
 
 
此run函数可以传递给另一个函数或类,并且那些操作的运行方式将是完全可互换的。记住你可以将函数作为参数传递。
 
 
结论
 
 
密封类的概念非常简单,但是如果您之前没有使用函数式编程,则需要一些使用新概念的基础。
 
 
我必须说,由于我在函数式编程方面的知识限制,我还没有最大限度的使用密封类。
 
 
如果您像我一样热衷于此,我建议你查看以前的文章,您可以在其中了解更多有关Kotlin的信息,或者在本书中了解如何使用Kotlin从头开始创建一个完整的Android应用程序。
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
val ui = Ui() +
        UiOp.Show +
       
UiOp.TranslateX(20f) +
       
UiOp.TranslateY(40f) +
        UiOp.Hide
 
run(view,
ui)转载自:https://www.cnblogs.com/figozhg/p/7107053.html 收起阅读 »

Android的Kotlin秘方(I):OnGlobalLayoutListener

春节后,又重新“开张”。各位高手请继续支持。谢谢!
 
 
原文标题:Kotlin recipes for Android (I): OnGlobalLayoutListener
原文链接:http://antonioleiva.com/kotlin ... ener/
原文作者:Antonio Leiva(http://antonioleiva.com/about/
原文发布:2016-03-16 ­
 
Android的Kotlin秘方(I):OnGlobalLayoutListener

 
今天一位同伴问我怎样恰当使用OnGlobalLayoutListener,而不需要太多的模板。这是一个棘手的问题,我们需要进一步深入研究。
 
OnGlobalLayoutListener是干什么的?
这个侦听器对于任何试图的ViewTreeObserver都适用,并且在已知视图宽度和高度进行各种计算、动画等等时,为扩展和测量视图常常回调它。
 
幸亏Kotlin提供很好的与Java互操作性,我们能够以一种非常清晰的方法 —— 使用它的模拟属性和Lambda表达式 —— 实现单一方法接口:

1 recycler.viewTreeObserver.addOnGlobalLayoutListener {
2 // do whatever
3 }

这里有什么问题吗?为了预防泄漏,推荐的实践是在完成使用它后,立即删除这个侦听器。但是由于使用了Lambda表达式,Lambda没有对象那么精确,我们没有对象的引用。
 
原方式还是可以用,但是在Kotlin中直接用匿名对象,每次都会有一只小猫死去。如果仍然需要做下面这样的事,没法改用更好开发语言:

1 recycler.viewTreeObserver.addOnGlobalLayoutListener(
2 object : ViewTreeObserver.OnGlobalLayoutListener {
3 override fun onGlobalLayout() {
4 recycler.viewTreeObserver.removeOnGlobalLayoutListener(this);
5 // do whatever
6 }
7 });

 
找一个更佳替换方法
好了,既已知不要那样做。那么有什么更好的方法吗?我们被迫使用一种看上去没有那么好看的方法,但是可能是一种好的选择,将扩展函数隐藏起来。
 
为视图接收另一个函数创建一个新函数,由它自己创建和删除侦听器。就像这样:

1 inline fun View.waitForLayout(crossinline f: () -> Unit) = with(viewTreeObserver) {
2 addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
3 override fun onGlobalLayout() {
4 removeOnGlobalLayoutListener(this)
5 f()
6 }
7 })
8 }

 
现在你就可以调用这个函数,确保其自己添加和删除侦听器。除非,你永远不会忘记删除:

1 recycler.waitForLayout {
2 // do whatever
3 }

 
如果喜欢,可以用扩展ViewTreeObserver的函数,而不是直接用View。这取决你。
 
但是我们仍可以改进它
这是在测试视图后布局侦听器通常要做的一些事,所以需要等待宽度和高度大于0。而且可能要在视图中调用它时做一些事,这为什么不能转换参数函数到扩展函数?
 
我还泛型该函数使它能够在任何继承View的对象中使用,也能够从编写的函数中访问所有它的指定函数和属性。

1 inline fun T.afterMeasured(crossinline f: T.() -> Unit) {
2 viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
3 override fun onGlobalLayout() {
4 if (measuredWidth > 0 && measuredHeight > 0) {
5 viewTreeObserver.removeOnGlobalLayoutListener(this)
6 f()
7 }
8 }
9 })
10 }

 
这个afterMeasured函数非常类似前者,但是在Lambda表达式内直接用视图的属性和public方法。例如,我们能够得到recycler的宽度和基于它用列的动态数组设置布局。

1 recycler.afterMeasured {
2 val columnCount = width / columnWidth
3 layoutManager = GridLayoutManager(context, columnCount)
4 }

总结
在Android中运行时,这确实仍有些事情做的不是很好,即使是移植Kotlin,但是总是可以通过隐藏在其他结构背后的不确定因素,找到提升可读性和避免不确定因素的选择。至少,仅需要编写一次,而其它代码则非常漂亮!
 转载自:https://www.cnblogs.com/figozhg/p/5313712.html
继续阅读 »
春节后,又重新“开张”。各位高手请继续支持。谢谢!
 
 
原文标题:Kotlin recipes for Android (I): OnGlobalLayoutListener
原文链接:http://antonioleiva.com/kotlin ... ener/
原文作者:Antonio Leiva(http://antonioleiva.com/about/
原文发布:2016-03-16 ­
 
Android的Kotlin秘方(I):OnGlobalLayoutListener

 
今天一位同伴问我怎样恰当使用OnGlobalLayoutListener,而不需要太多的模板。这是一个棘手的问题,我们需要进一步深入研究。
 
OnGlobalLayoutListener是干什么的?
这个侦听器对于任何试图的ViewTreeObserver都适用,并且在已知视图宽度和高度进行各种计算、动画等等时,为扩展和测量视图常常回调它。
 
幸亏Kotlin提供很好的与Java互操作性,我们能够以一种非常清晰的方法 —— 使用它的模拟属性和Lambda表达式 —— 实现单一方法接口:

1 recycler.viewTreeObserver.addOnGlobalLayoutListener {
2 // do whatever
3 }

这里有什么问题吗?为了预防泄漏,推荐的实践是在完成使用它后,立即删除这个侦听器。但是由于使用了Lambda表达式,Lambda没有对象那么精确,我们没有对象的引用。
 
原方式还是可以用,但是在Kotlin中直接用匿名对象,每次都会有一只小猫死去。如果仍然需要做下面这样的事,没法改用更好开发语言:

1 recycler.viewTreeObserver.addOnGlobalLayoutListener(
2 object : ViewTreeObserver.OnGlobalLayoutListener {
3 override fun onGlobalLayout() {
4 recycler.viewTreeObserver.removeOnGlobalLayoutListener(this);
5 // do whatever
6 }
7 });

 
找一个更佳替换方法
好了,既已知不要那样做。那么有什么更好的方法吗?我们被迫使用一种看上去没有那么好看的方法,但是可能是一种好的选择,将扩展函数隐藏起来。
 
为视图接收另一个函数创建一个新函数,由它自己创建和删除侦听器。就像这样:

1 inline fun View.waitForLayout(crossinline f: () -> Unit) = with(viewTreeObserver) {
2 addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
3 override fun onGlobalLayout() {
4 removeOnGlobalLayoutListener(this)
5 f()
6 }
7 })
8 }

 
现在你就可以调用这个函数,确保其自己添加和删除侦听器。除非,你永远不会忘记删除:

1 recycler.waitForLayout {
2 // do whatever
3 }

 
如果喜欢,可以用扩展ViewTreeObserver的函数,而不是直接用View。这取决你。
 
但是我们仍可以改进它
这是在测试视图后布局侦听器通常要做的一些事,所以需要等待宽度和高度大于0。而且可能要在视图中调用它时做一些事,这为什么不能转换参数函数到扩展函数?
 
我还泛型该函数使它能够在任何继承View的对象中使用,也能够从编写的函数中访问所有它的指定函数和属性。

1 inline fun T.afterMeasured(crossinline f: T.() -> Unit) {
2 viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
3 override fun onGlobalLayout() {
4 if (measuredWidth > 0 && measuredHeight > 0) {
5 viewTreeObserver.removeOnGlobalLayoutListener(this)
6 f()
7 }
8 }
9 })
10 }

 
这个afterMeasured函数非常类似前者,但是在Lambda表达式内直接用视图的属性和public方法。例如,我们能够得到recycler的宽度和基于它用列的动态数组设置布局。

1 recycler.afterMeasured {
2 val columnCount = width / columnWidth
3 layoutManager = GridLayoutManager(context, columnCount)
4 }

总结
在Android中运行时,这确实仍有些事情做的不是很好,即使是移植Kotlin,但是总是可以通过隐藏在其他结构背后的不确定因素,找到提升可读性和避免不确定因素的选择。至少,仅需要编写一次,而其它代码则非常漂亮!
 转载自:https://www.cnblogs.com/figozhg/p/5313712.html 收起阅读 »

android json 解析 kotlin

 
  前面 写了一次 kotlin解析json 但是,真的写得太烂,直接删掉了,现在重新整理一下。顺便记录一下今天坑了我很久的小问题。
 
  1.首先从最简单的入手吧
  一个json的字符串:=====就叫做jsonString吧

 {
    "code": "200",
    "msg": "success",
    "debugMsg": "",
    "result": {
        "data": "1231414"
        }
  }

 
       好了怎么解析呢???
  用一个函数即可

fun get_key_string(key:String,jsonString:String):String {
var str: String = ""
try {

val jsonObj:JSONObject= JSONObject(jsonString)
str=jsonObj.getString(key)
} catch (e: JSONException) {
e.printStackTrace()
}
return str
}

  怎么用呢???
  val msg=get_key_string("msg","jsonString")
  第一个参数=====在json字符串中,你想要解析的key,我上面的例子有 code,msg,debugMsg,result,我选择的是msg
  第二个参数=====就是json字符串的名称,就是一个字符串,不要想得太复杂了
  msg解析后的结果=====success
 
  2.多重解析
  依旧是上面的例子吧=====json字符串名字依旧叫做jsonString

 {
    "code": "200",
    "msg": "success",
    "debugMsg": "",
    "result": {
        "data": "1231414"
        }
  }

  我想要得到data怎么办呢???
  很简单,两步即可。
  val result=get_key_String("result","jsonString")//=====这里的第二个参数依旧是jsonString
  val data=get_key_String("data","result")//=====注意这里的第二个参数已经变成了result了
 
  3.解析整型,boolean类型
  这个和解析String类型类似,直接上代码吧
  

fun get_key_boolean(key:String,jsonString:String):Boolean {//解析成Boolean
var str: Boolean =true
try {
val jsonObj:JSONObject= JSONObject(jsonString)
str=jsonObj.getBoolean(key)
} catch (e: JSONException) {
e.printStackTrace()
}
return str
}

fun get_key_int(key:String,jsonString:String):Int {//解析成Int
var str: Int=0
try {
val jsonObj:JSONObject= JSONObject(jsonString)
str=jsonObj.getInt(key)
} catch (e: JSONException) {
e.printStackTrace()
}
return str
}

 
  4.稍微牛逼一点的解析=====解析成List>=====其实这个就比较通用了,很多东西直接用这个就可以了
  比如来一个复杂一点的jsonString吧
 

{
"code": "200",
"msg": "success",
"debugMsg": "",
"result": {
"data": [
       "key1": "string" "key2": 123 "key3": true
]
}}

  这样一个jsonString,key1对应一个字符串,key2对应一个整型,key3对应一个布尔类型
  怎么解析呢???

fun getListMap(key: String, jsonString: String): List> {
val list = ArrayList>()
try {
val jsonObject = JSONObject(jsonString)
val jsonArray = jsonObject.getJSONArray(key)
for (i in 0..jsonArray.length() - 1) {
val jsonObject2 = jsonArray.getJSONObject(i)
val map = HashMap()
val iterator = jsonObject2.keys()
while (iterator.hasNext()) {
val json_key = iterator.next()
var json_value: Any? = jsonObject2.get(json_key)
if (json_value == null) {
json_value = ""
}
map.put(json_key, json_value)
}
list.add(map)
}
} catch (e: JSONException) {

e.printStackTrace()
}
return list
}

 
  主要有2个步骤
  val result=get_key_string("result","jsonString")
  val data=getListMap("data","result")
  就这么666
 
  5.将所有的可以用到的方法封装起来吧


class JsonUtil {
companion object {


fun get_key_string(key:String,jsonString:String):String {
var str: String = ""

try {

val jsonObj:JSONObject= JSONObject(jsonString)
str=jsonObj.getString(key)


} catch (e: JSONException) {
e.printStackTrace()
}
return str
}

fun get_key_boolean(key:String,jsonString:String):Boolean {
var str: Boolean =true
try {
val jsonObj:JSONObject= JSONObject(jsonString)
str=jsonObj.getBoolean(key)
} catch (e: JSONException) {
e.printStackTrace()
}
return str
}

fun get_key_int(key:String,jsonString:String):Int {
var str: Int=0
try {
val jsonObj:JSONObject= JSONObject(jsonString)
str=jsonObj.getInt(key)
} catch (e: JSONException) {
e.printStackTrace()
}
return str
}


fun getList(key: String, jsonString: String): List {
val list = ArrayList()
try {
val jsonObject = JSONObject(jsonString)
val jsonArray = jsonObject.getJSONArray(key)
for (i in 0..jsonArray.length() - 1) {
val msg = jsonArray.getString(i)
list.add(msg)
}
} catch (e: JSONException) {
e.printStackTrace()
}

return list
}


fun getListMap(key: String, jsonString: String): List> {
val list = ArrayList>()
try {
val jsonObject = JSONObject(jsonString)
val jsonArray = jsonObject.getJSONArray(key)
for (i in 0..jsonArray.length() - 1) {
val jsonObject2 = jsonArray.getJSONObject(i)
val map = HashMap()
val iterator = jsonObject2.keys()
while (iterator.hasNext()) {
val json_key = iterator.next()
var json_value: Any? = jsonObject2.get(json_key)
if (json_value == null) {
json_value = ""
}
map.put(json_key, json_value)
}
list.add(map)
}
} catch (e: JSONException) {

e.printStackTrace()
}
return list
}


fun get_ask_Item(key:String,jsonString:String): ArrayList? {
var myAsk=ArrayList()
try{
val jsonObject=JSONObject(jsonString)
val jsonArray=jsonObject.getJSONArray(key)
for(i in 0..jsonArray.length()-1){
val json_ask=jsonArray.getJSONObject(i)
var my_ask=MyAsk()
val commentCount=json_ask.getString("commentCount")
val commentID=json_ask.getString("commentID")
val content=json_ask.getString("content")
val createTime=json_ask.getString("createTime")
val gender=json_ask.getString("gender")
val icon=json_ask.getString("icon")
val id=json_ask.getString("id")
val isFavorite=json_ask.getString("isFavorite")
val isZan=json_ask.getString("isZan")
val label=json_ask.getString("label")
val link=json_ask.getString("link")
val nickname=json_ask.getString("nickname")
val publisherID=json_ask.getString("publisherID")
val reward=json_ask.getString("reward")
val type=json_ask.getString("type")
val zan=json_ask.getString("zan")

val image_array=json_ask.getJSONArray("image")
var image_list:ArrayList?=null
for(j1 in 0..image_array.length()-1){
val image_item=image_array.getString(j1)
image_list?.add(image_item)
}

val thumbnailImage_array=json_ask.getJSONArray("thumbnailImage")
var image_list2:ArrayList?=null
for(j2 in 0..thumbnailImage_array.length()-1){
val image_item=thumbnailImage_array.getString(j2)
image_list2?.add(image_item)
}

my_ask.commentID=commentID
my_ask.commentCount=commentCount
my_ask.content=content
my_ask.createTime=createTime
my_ask.gender=gender
my_ask.icon=icon
my_ask.id=id
my_ask.favoriteIs=isFavorite
my_ask.zan=zan
my_ask.zanIs=isZan
my_ask.label=label
my_ask.link=link
my_ask.nickname=nickname
my_ask.publisherID=publisherID
my_ask.reward=reward
my_ask.type=type
my_ask.image=image_list
my_ask.thumbnailImage=image_list2

myAsk?.add(my_ask)
}
return myAsk
}catch (e:JSONException){
e.printStackTrace()
}
return myAsk
}

}

}

View Code
  最后一种是自定义式解析,因为项目中的jsonString可以非常复杂,所以要自己定义一个类,然后用类似的方法来解析即可。
  因为我博客名也叫做Jason_Jan对于json还是比较情有独钟的,可以说json真的很棒
  
  推荐两个第三方库
  Ason=====github链接:https://github.com/afollestad/ason
  GsonFormat=====github链接:https://github.com/zzz40500/GsonFormat
 
 
 
  
 转载自:https://www.cnblogs.com/Jason-Jan/p/7262515.html
继续阅读 »
 
  前面 写了一次 kotlin解析json 但是,真的写得太烂,直接删掉了,现在重新整理一下。顺便记录一下今天坑了我很久的小问题。
 
  1.首先从最简单的入手吧
  一个json的字符串:=====就叫做jsonString吧

 {
    "code": "200",
    "msg": "success",
    "debugMsg": "",
    "result": {
        "data": "1231414"
        }
  }

 
       好了怎么解析呢???
  用一个函数即可

fun get_key_string(key:String,jsonString:String):String {
var str: String = ""
try {

val jsonObj:JSONObject= JSONObject(jsonString)
str=jsonObj.getString(key)
} catch (e: JSONException) {
e.printStackTrace()
}
return str
}

  怎么用呢???
  val msg=get_key_string("msg","jsonString")
  第一个参数=====在json字符串中,你想要解析的key,我上面的例子有 code,msg,debugMsg,result,我选择的是msg
  第二个参数=====就是json字符串的名称,就是一个字符串,不要想得太复杂了
  msg解析后的结果=====success
 
  2.多重解析
  依旧是上面的例子吧=====json字符串名字依旧叫做jsonString

 {
    "code": "200",
    "msg": "success",
    "debugMsg": "",
    "result": {
        "data": "1231414"
        }
  }

  我想要得到data怎么办呢???
  很简单,两步即可。
  val result=get_key_String("result","jsonString")//=====这里的第二个参数依旧是jsonString
  val data=get_key_String("data","result")//=====注意这里的第二个参数已经变成了result了
 
  3.解析整型,boolean类型
  这个和解析String类型类似,直接上代码吧
  

fun get_key_boolean(key:String,jsonString:String):Boolean {//解析成Boolean
var str: Boolean =true
try {
val jsonObj:JSONObject= JSONObject(jsonString)
str=jsonObj.getBoolean(key)
} catch (e: JSONException) {
e.printStackTrace()
}
return str
}

fun get_key_int(key:String,jsonString:String):Int {//解析成Int
var str: Int=0
try {
val jsonObj:JSONObject= JSONObject(jsonString)
str=jsonObj.getInt(key)
} catch (e: JSONException) {
e.printStackTrace()
}
return str
}

 
  4.稍微牛逼一点的解析=====解析成List>=====其实这个就比较通用了,很多东西直接用这个就可以了
  比如来一个复杂一点的jsonString吧
 

{
"code": "200",
"msg": "success",
"debugMsg": "",
"result": {
"data": [
       "key1": "string" "key2": 123 "key3": true
]
}}

  这样一个jsonString,key1对应一个字符串,key2对应一个整型,key3对应一个布尔类型
  怎么解析呢???

fun getListMap(key: String, jsonString: String): List> {
val list = ArrayList>()
try {
val jsonObject = JSONObject(jsonString)
val jsonArray = jsonObject.getJSONArray(key)
for (i in 0..jsonArray.length() - 1) {
val jsonObject2 = jsonArray.getJSONObject(i)
val map = HashMap()
val iterator = jsonObject2.keys()
while (iterator.hasNext()) {
val json_key = iterator.next()
var json_value: Any? = jsonObject2.get(json_key)
if (json_value == null) {
json_value = ""
}
map.put(json_key, json_value)
}
list.add(map)
}
} catch (e: JSONException) {

e.printStackTrace()
}
return list
}

 
  主要有2个步骤
  val result=get_key_string("result","jsonString")
  val data=getListMap("data","result")
  就这么666
 
  5.将所有的可以用到的方法封装起来吧


class JsonUtil {
companion object {


fun get_key_string(key:String,jsonString:String):String {
var str: String = ""

try {

val jsonObj:JSONObject= JSONObject(jsonString)
str=jsonObj.getString(key)


} catch (e: JSONException) {
e.printStackTrace()
}
return str
}

fun get_key_boolean(key:String,jsonString:String):Boolean {
var str: Boolean =true
try {
val jsonObj:JSONObject= JSONObject(jsonString)
str=jsonObj.getBoolean(key)
} catch (e: JSONException) {
e.printStackTrace()
}
return str
}

fun get_key_int(key:String,jsonString:String):Int {
var str: Int=0
try {
val jsonObj:JSONObject= JSONObject(jsonString)
str=jsonObj.getInt(key)
} catch (e: JSONException) {
e.printStackTrace()
}
return str
}


fun getList(key: String, jsonString: String): List {
val list = ArrayList()
try {
val jsonObject = JSONObject(jsonString)
val jsonArray = jsonObject.getJSONArray(key)
for (i in 0..jsonArray.length() - 1) {
val msg = jsonArray.getString(i)
list.add(msg)
}
} catch (e: JSONException) {
e.printStackTrace()
}

return list
}


fun getListMap(key: String, jsonString: String): List> {
val list = ArrayList>()
try {
val jsonObject = JSONObject(jsonString)
val jsonArray = jsonObject.getJSONArray(key)
for (i in 0..jsonArray.length() - 1) {
val jsonObject2 = jsonArray.getJSONObject(i)
val map = HashMap()
val iterator = jsonObject2.keys()
while (iterator.hasNext()) {
val json_key = iterator.next()
var json_value: Any? = jsonObject2.get(json_key)
if (json_value == null) {
json_value = ""
}
map.put(json_key, json_value)
}
list.add(map)
}
} catch (e: JSONException) {

e.printStackTrace()
}
return list
}


fun get_ask_Item(key:String,jsonString:String): ArrayList? {
var myAsk=ArrayList()
try{
val jsonObject=JSONObject(jsonString)
val jsonArray=jsonObject.getJSONArray(key)
for(i in 0..jsonArray.length()-1){
val json_ask=jsonArray.getJSONObject(i)
var my_ask=MyAsk()
val commentCount=json_ask.getString("commentCount")
val commentID=json_ask.getString("commentID")
val content=json_ask.getString("content")
val createTime=json_ask.getString("createTime")
val gender=json_ask.getString("gender")
val icon=json_ask.getString("icon")
val id=json_ask.getString("id")
val isFavorite=json_ask.getString("isFavorite")
val isZan=json_ask.getString("isZan")
val label=json_ask.getString("label")
val link=json_ask.getString("link")
val nickname=json_ask.getString("nickname")
val publisherID=json_ask.getString("publisherID")
val reward=json_ask.getString("reward")
val type=json_ask.getString("type")
val zan=json_ask.getString("zan")

val image_array=json_ask.getJSONArray("image")
var image_list:ArrayList?=null
for(j1 in 0..image_array.length()-1){
val image_item=image_array.getString(j1)
image_list?.add(image_item)
}

val thumbnailImage_array=json_ask.getJSONArray("thumbnailImage")
var image_list2:ArrayList?=null
for(j2 in 0..thumbnailImage_array.length()-1){
val image_item=thumbnailImage_array.getString(j2)
image_list2?.add(image_item)
}

my_ask.commentID=commentID
my_ask.commentCount=commentCount
my_ask.content=content
my_ask.createTime=createTime
my_ask.gender=gender
my_ask.icon=icon
my_ask.id=id
my_ask.favoriteIs=isFavorite
my_ask.zan=zan
my_ask.zanIs=isZan
my_ask.label=label
my_ask.link=link
my_ask.nickname=nickname
my_ask.publisherID=publisherID
my_ask.reward=reward
my_ask.type=type
my_ask.image=image_list
my_ask.thumbnailImage=image_list2

myAsk?.add(my_ask)
}
return myAsk
}catch (e:JSONException){
e.printStackTrace()
}
return myAsk
}

}

}

View Code
  最后一种是自定义式解析,因为项目中的jsonString可以非常复杂,所以要自己定义一个类,然后用类似的方法来解析即可。
  因为我博客名也叫做Jason_Jan对于json还是比较情有独钟的,可以说json真的很棒
  
  推荐两个第三方库
  Ason=====github链接:https://github.com/afollestad/ason
  GsonFormat=====github链接:https://github.com/zzz40500/GsonFormat
 
 
 
  
 转载自:https://www.cnblogs.com/Jason-Jan/p/7262515.html 收起阅读 »

Kotlin学习笔记(2):run、apply、let、also、with的用法和区别

run 、 apply 、 let 、 also 和 with 五个函数均位于 kotlin 包下的 Standard 文件中,其含义和用法比较相似,现分别介绍如下。
run
用法1
函数定义:
public inline fun run(block: () -> R): R = block()
功能:调用run函数块。返回值为函数块最后一行,或者指定return表达式。
示例:
val a = run {
println("run")
return@run 3
}
println(a)
运行结果:
run
3
用法2
函数定义:
public inline fun T.run(block: T.() -> R): R = block()
功能:调用某对象的run函数,在函数块内可以通过 this 指代该对象。返回值为函数块的最后一行或指定return表达式。
示例:
val a = "string".run {
println(this)
3
}
println(a)
运行结果:
string
3
apply
函数定义:
public inline fun T.apply(block: T.() -> Unit): T { block(); return this }
功能:调用某对象的apply函数,在函数块内可以通过 this 指代该对象。返回值为该对象自己。
示例:
val a = "string".apply {
println(this)
}
println(a)
运行结果:
string
string
let
函数定义:
public inline fun T.let(block: (T) -> R): R = block(this)
功能:调用某对象的let函数,则该对象为函数的参数。在函数块内可以通过 it 指代该对象。返回值为函数块的最后一行或指定return表达式。
示例:
val a = "string".let {
println(it)
3
}
println(a)
运行结果:
string
3
also
函数定义(Kotlin1.1新增的):
public inline fun T.also(block: (T) -> Unit): T { block(this); return this }
功能:调用某对象的also函数,则该对象为函数的参数。在函数块内可以通过 it 指代该对象。返回值为该对象自己。
示例:
val a = "string".also {
println(it)
}
println(a)
运行结果:
string
string
with
函数定义:
public inline fun with(receiver: T, block: T.() -> R): R = receiver.block()
功能:with函数和前面的几个函数使用方式略有不同,因为它不是以扩展的形式存在的。它是将某对象作为函数的参数,在函数块内可以通过 this 指代该对象。返回值为函数块的最后一行或指定return表达式。
示例:
val a = with("string") {
println(this)
3
}
println(a)
运行结果:
string
3
参考资料
What's New in Kotlin 1.1 - also(), takeIf() and takeUnless()[](https://kotlinlang.org/docs/re ... unless)转载自:https://www.cnblogs.com/duduhuo/p/6934137.html
继续阅读 »
run 、 apply 、 let 、 also 和 with 五个函数均位于 kotlin 包下的 Standard 文件中,其含义和用法比较相似,现分别介绍如下。
run
用法1
函数定义:
public inline fun run(block: () -> R): R = block()
功能:调用run函数块。返回值为函数块最后一行,或者指定return表达式。
示例:
val a = run {
println("run")
return@run 3
}
println(a)
运行结果:
run
3
用法2
函数定义:
public inline fun T.run(block: T.() -> R): R = block()
功能:调用某对象的run函数,在函数块内可以通过 this 指代该对象。返回值为函数块的最后一行或指定return表达式。
示例:
val a = "string".run {
println(this)
3
}
println(a)
运行结果:
string
3
apply
函数定义:
public inline fun T.apply(block: T.() -> Unit): T { block(); return this }
功能:调用某对象的apply函数,在函数块内可以通过 this 指代该对象。返回值为该对象自己。
示例:
val a = "string".apply {
println(this)
}
println(a)
运行结果:
string
string
let
函数定义:
public inline fun T.let(block: (T) -> R): R = block(this)
功能:调用某对象的let函数,则该对象为函数的参数。在函数块内可以通过 it 指代该对象。返回值为函数块的最后一行或指定return表达式。
示例:
val a = "string".let {
println(it)
3
}
println(a)
运行结果:
string
3
also
函数定义(Kotlin1.1新增的):
public inline fun T.also(block: (T) -> Unit): T { block(this); return this }
功能:调用某对象的also函数,则该对象为函数的参数。在函数块内可以通过 it 指代该对象。返回值为该对象自己。
示例:
val a = "string".also {
println(it)
}
println(a)
运行结果:
string
string
with
函数定义:
public inline fun with(receiver: T, block: T.() -> R): R = receiver.block()
功能:with函数和前面的几个函数使用方式略有不同,因为它不是以扩展的形式存在的。它是将某对象作为函数的参数,在函数块内可以通过 this 指代该对象。返回值为函数块的最后一行或指定return表达式。
示例:
val a = with("string") {
println(this)
3
}
println(a)
运行结果:
string
3
参考资料
What's New in Kotlin 1.1 - also(), takeIf() and takeUnless()[](https://kotlinlang.org/docs/re ... unless)转载自:https://www.cnblogs.com/duduhuo/p/6934137.html 收起阅读 »

kotlin 练习

kotlin基础语法
 
samychen 关注
2017.05.28 17:07* 字数 1224 阅读 2434评论 0喜欢 6




每种编程语言都有一定的语法、语义和执行顺序(同步),学习一种新语言也都是从这三者出发,下面我们就只针对kotlin的语法来做简单的介绍。
Kotlin有自己的特性不该被Java的思维所束缚。

基本语法准则:在Kotlin中常量用 val 声明,变量用 var 声明;关键字在前面,类型以冒号 :隔开在后面,也可以省略直接赋值;类型后带问号 ? 表示可为空类型(默认空类型安全);常量 val 延迟加载 by lazy{} ;默认是线程安全的,关闭线程安全 lazy(LazyThreadSafetyMode.NONE){} ;变量 var 延迟加载 lateinit ;内部类和参数默认为public,而在Java中为private类默认为不可继承(final),想要可被继承要声明为 open 或 abstract取消了static关键字,静态方法和参数统一写在 companion object 块internal模块内可见,inner内部类


//常量数组int[][][] arrs = new int[3][2][1];
val arrs = Array(3) { Array(2) { IntArray(1) } }
internal var name: String? = null//类型后带问号 ? 表示可为空类型(默认空安全)
internal var age: Int = 0//internal模块内可见,inner内部类
//当我们只有单个构造器时,我们需要在从父类继承下来的构造器中指定需要的参数。这是用来替换Java中的super调用的。
open class Animal(name: String)
class Person(name: String, surname: String) : Animal(name)

kotlin是空类型安全的,所有变量默认为"not null",必须显式在类型后添加?修饰符才可赋值为null。
var notNullArtist: Artist = null//编译不通过,因为notNullArtist不能为null
var artist: Artist? = null//编译通过
artist.print()//编译不通过,因为artist可能为空
/** Kotlin进行空判断处理,有两种处理方式:
* 1. 抛出空异常,字段后加 !!
* 2. 不做处理直接跳过,字段后加 ?
*/
artist?.print()//编译通过,做了非空判断,只有当artist!=null时才调用print()
artist!!.print()//这种用法只有在确认artist不为null时才能调用,否则抛出空指针异常
val name = artist?.name?:"empty"//当artist为null时可以指定一个默认值


条件语句if...else 正常使用,不过移除了 switch 用更强大的 when 替代,when子式可以是各种返回Boolean的表达式


val x = 7
when (x) {
in 1..5 -> print("x is in the range")
in validNumbers -> print("x is valid")
!in 10..20 -> print("x is outside the range")
else -> print("none of the above")
}

kotlin尽可能多的使用when

循环语句while 和 do...while 同Java并无区别, for 则有很大改变并多出了几个变种


fun main(args: Array) {
var list = ArrayList()
add(list)
list.forEachIndexed { i, s ->
print(list[i])
print(s)
}
println()
//如果没有指定函数的返回值,它就会返回Unit,与Java中的void类似,但是Unit是一个真正的对象。当然也可以指定任何其它的返回类型:
list.forEachIndexed(object :(Int,String) -> Unit{
override fun invoke(i: Int, s: String) {
print(list[i])
print(s)
}
})
}
//递增for (int i = 0; i < list.size(); i++)
for (i in list.indices) {
print(list[i])
}
//递增for (int i = 2; i < list.size(); i++)
for (i in 2..list.size-1) {
print(list[i])
}
//递减for (int i = list.size(); i >= 0; i--)
for (i in list.size downTo 0) {
print(list[i])
}
//操作列表内的对象
for (item in list) {
print(item)
}
//加强版
for((i,item) in list.withIndex()){
print(list[i])
print(item)
}
//变种版
list.forEach {
print(it)
}

list.forEachIndexed { i, s ->
print(list[i])
print(s)
}

list.forEachIndexed(object :(Int,String) -> Unit{
override fun invoke(i: Int, s: String) {
print(list[i])
print(s)
}
})
fun add(list:MutableList) {
for (i in 0..4) {
list.add(i.toString() + "")
}
}

冒号使用  在Kotlin中冒号 : 用万能来称呼绝不为过。常量变量的类型声明,函数的返回值,类的继承都需要它
除此之外还有一个特别的地方也需要它,使用Java类的时候。Kotlin最终会还是编译成Java字节码,使用到Java类是必然的,在Kotlin语法如下val intent = Intent(this, MainActivity::class.java)
指定上下文的@
除了冒号另一个重要符号 @ ,java代码中经常用到内部类和匿名内部类,有时我们不能确定this指代的上下文,Java可以使用XXX.this指代具体上下文,在kotlin中的做法是this@XXX
class User {
inner class State{
fun getUser(): User{
//返回User
return this@User
}
fun getState(): State{
//返回State
return this@State
}
}
}

kotlin的特色
Java的 getter/setter 方法自动转换成属性,对应到Kotlin属性的调用
public class User {
private String name;
private String age;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getAge() {
return age;
}

public void setAge(String age) {
this.age = age;
}
}

对应的kotlin
val user = User()
//赋值
user.name = "tutu"
user.age = "23"
//取值
val name = user.name
val age = user.age

class User {
var name: String? = null
var age: String? = null
}

有时 getter/setter 方法比较复杂,这就需要自定义 getter/setter 了,实现一个Java中常用的单例,这里只为了展示,单例在Kotlin有更简单的方法实现,只要在 package 级别创建一个 object 即可
class User {
companion object {//静态方法和参数统一写在 companion object 块
//volatile不保证原子操作,所以,很容易读到脏数据。在两个或者更多的线程访问的成员变量上使用volatile
@Volatile var instance: User? = null
get() {
if (field == null) {
synchronized(User::class.java) {
if (field == null)
field = User()
}
}
return field
}
}

var name: String? = null
var age: String? = null
}

自定义 getter/setter 重点在 field ,跟我们熟悉所Java的 this 指代当前类一样, field 指代当前参数,直接使用参数名 instance 代替不会报错但单例就没效果了
字符串问题
在Java中拼接字符串的代码可读性都很差,在Kotlin字符串拼接变得非常简洁,只需用 $ 后面加上参数名,复杂的参数要加上 {}
val pair = Pair(1, "one")
val (num, name) = pair
println("num = $num, name = $name")

输出num = 1, name = one
Java8新特性lambda的支持
lambda需要一个函数,但是又不想费神去命名一个函数的场合下使用,也就是指匿名函数。使用功能接口,把接口名、方法名和参数类型省掉不写再加个 -> 罢了。
使用Java开发Android时,处理监听回调是常见的事,kotlin可以直接编写监听回调而不用再通过匿名对象传递onClick方法,这个特性被称为Lambda表达式
view.setOnclickListener({
Toast.makeText(this, "Hello World!", Toast.LENGTH_LONG).show()
})

扩展函数
可以为任何已经存在的类添加新函数,相比传统工具类,扩展函数更具有可读性。
//为Fragment添加扩展函数
fun Fragment.toast(message: CharSequence, duration: Int = Toast.LENGTH_LONG){
Toast.makeText(getActivity(), message, duration).show()
}

调用时直接调用fragment.toast("Hello World!")或fragment.toast("Hello World!", 2000)
Kotlin中的参数与Java中有些不同。如你所见,我们先写参数的名字再写它的类型。上面调用的第二个参数(length)指定了一个默认值。这意味着你调用的时候可以传入第二个值或者不传,这样可以避免你需要的重载函数。
函数式支持(lambda),函数是一级公民
集合操作
  list转map(associateBy)
  场景:订单列表转换成以 id为key 的订单map
val mainOrders = orderDao!!.queryUserOrder(param)
val orderMap = mainOrders.associateBy { it.id }.toMap()

  map的key或者value转换
  假如一个map的key是String,需要转换成Long;或者map的value是一个对象,要转成另一个对象。按照标准Java写法,可以要new一个新的map,然后循环老的map,在kotlin中,一行代码搞定
val map = mutableMapOf(1 to 1, 2 to 2)
val newMap = map.mapKeys { "key_${it.key}" }.mapValues { "value_${it.value}" }
println(newMap)
//打印结果 {key_1=value_1, key_2=value_2}
val pair = Pair("ss","sg")
val map = mapOf(pair)
val map1=map.mapKeys { entry -> "${entry.value}!" }
for((key,value) in map1){
println("map1:key=$key")
println("map1:value=$value")
}
val map2 =map.mapKeys { (key, value) -> "$value" }
for((key,value) in map2){
println("map2:key=$key")
println("map2:value=$value")
}
val map3=map.mapValues { entry -> "${entry.value}!" }
for((key,value) in map3){
println("map3:key=$key")
println("map3:value=$value")
}
val map4=map.mapValues { (key, value) -> "$value" }
for((key,value) in map4){
println("map4:key=$key")
println("map4:value=$value")
}
打印结果:
map1:key=sg!
map1:value=sg
map2:key=sg
map2:value=sg
map3:key=ss
map3:value=sg!
map4:key=ss
map4:value=sg

参考文献  Kotlin for android Developers  kotlin 脚本练习转载自:https://www.cnblogs.com/vana/p/10201277.html
继续阅读 »
kotlin基础语法
 
samychen 关注
2017.05.28 17:07* 字数 1224 阅读 2434评论 0喜欢 6




每种编程语言都有一定的语法、语义和执行顺序(同步),学习一种新语言也都是从这三者出发,下面我们就只针对kotlin的语法来做简单的介绍。
Kotlin有自己的特性不该被Java的思维所束缚。

基本语法准则:在Kotlin中常量用 val 声明,变量用 var 声明;关键字在前面,类型以冒号 :隔开在后面,也可以省略直接赋值;类型后带问号 ? 表示可为空类型(默认空类型安全);常量 val 延迟加载 by lazy{} ;默认是线程安全的,关闭线程安全 lazy(LazyThreadSafetyMode.NONE){} ;变量 var 延迟加载 lateinit ;内部类和参数默认为public,而在Java中为private类默认为不可继承(final),想要可被继承要声明为 open 或 abstract取消了static关键字,静态方法和参数统一写在 companion object 块internal模块内可见,inner内部类


//常量数组int[][][] arrs = new int[3][2][1];
val arrs = Array(3) { Array(2) { IntArray(1) } }
internal var name: String? = null//类型后带问号 ? 表示可为空类型(默认空安全)
internal var age: Int = 0//internal模块内可见,inner内部类
//当我们只有单个构造器时,我们需要在从父类继承下来的构造器中指定需要的参数。这是用来替换Java中的super调用的。
open class Animal(name: String)
class Person(name: String, surname: String) : Animal(name)

kotlin是空类型安全的,所有变量默认为"not null",必须显式在类型后添加?修饰符才可赋值为null。
var notNullArtist: Artist = null//编译不通过,因为notNullArtist不能为null
var artist: Artist? = null//编译通过
artist.print()//编译不通过,因为artist可能为空
/** Kotlin进行空判断处理,有两种处理方式:
* 1. 抛出空异常,字段后加 !!
* 2. 不做处理直接跳过,字段后加 ?
*/
artist?.print()//编译通过,做了非空判断,只有当artist!=null时才调用print()
artist!!.print()//这种用法只有在确认artist不为null时才能调用,否则抛出空指针异常
val name = artist?.name?:"empty"//当artist为null时可以指定一个默认值


条件语句if...else 正常使用,不过移除了 switch 用更强大的 when 替代,when子式可以是各种返回Boolean的表达式


val x = 7
when (x) {
in 1..5 -> print("x is in the range")
in validNumbers -> print("x is valid")
!in 10..20 -> print("x is outside the range")
else -> print("none of the above")
}

kotlin尽可能多的使用when

循环语句while 和 do...while 同Java并无区别, for 则有很大改变并多出了几个变种


fun main(args: Array) {
var list = ArrayList()
add(list)
list.forEachIndexed { i, s ->
print(list[i])
print(s)
}
println()
//如果没有指定函数的返回值,它就会返回Unit,与Java中的void类似,但是Unit是一个真正的对象。当然也可以指定任何其它的返回类型:
list.forEachIndexed(object :(Int,String) -> Unit{
override fun invoke(i: Int, s: String) {
print(list[i])
print(s)
}
})
}
//递增for (int i = 0; i < list.size(); i++)
for (i in list.indices) {
print(list[i])
}
//递增for (int i = 2; i < list.size(); i++)
for (i in 2..list.size-1) {
print(list[i])
}
//递减for (int i = list.size(); i >= 0; i--)
for (i in list.size downTo 0) {
print(list[i])
}
//操作列表内的对象
for (item in list) {
print(item)
}
//加强版
for((i,item) in list.withIndex()){
print(list[i])
print(item)
}
//变种版
list.forEach {
print(it)
}

list.forEachIndexed { i, s ->
print(list[i])
print(s)
}

list.forEachIndexed(object :(Int,String) -> Unit{
override fun invoke(i: Int, s: String) {
print(list[i])
print(s)
}
})
fun add(list:MutableList) {
for (i in 0..4) {
list.add(i.toString() + "")
}
}

冒号使用  在Kotlin中冒号 : 用万能来称呼绝不为过。常量变量的类型声明,函数的返回值,类的继承都需要它
除此之外还有一个特别的地方也需要它,使用Java类的时候。Kotlin最终会还是编译成Java字节码,使用到Java类是必然的,在Kotlin语法如下val intent = Intent(this, MainActivity::class.java)
指定上下文的@
除了冒号另一个重要符号 @ ,java代码中经常用到内部类和匿名内部类,有时我们不能确定this指代的上下文,Java可以使用XXX.this指代具体上下文,在kotlin中的做法是this@XXX
class User {
inner class State{
fun getUser(): User{
//返回User
return this@User
}
fun getState(): State{
//返回State
return this@State
}
}
}

kotlin的特色
Java的 getter/setter 方法自动转换成属性,对应到Kotlin属性的调用
public class User {
private String name;
private String age;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getAge() {
return age;
}

public void setAge(String age) {
this.age = age;
}
}

对应的kotlin
val user = User()
//赋值
user.name = "tutu"
user.age = "23"
//取值
val name = user.name
val age = user.age

class User {
var name: String? = null
var age: String? = null
}

有时 getter/setter 方法比较复杂,这就需要自定义 getter/setter 了,实现一个Java中常用的单例,这里只为了展示,单例在Kotlin有更简单的方法实现,只要在 package 级别创建一个 object 即可
class User {
companion object {//静态方法和参数统一写在 companion object 块
//volatile不保证原子操作,所以,很容易读到脏数据。在两个或者更多的线程访问的成员变量上使用volatile
@Volatile var instance: User? = null
get() {
if (field == null) {
synchronized(User::class.java) {
if (field == null)
field = User()
}
}
return field
}
}

var name: String? = null
var age: String? = null
}

自定义 getter/setter 重点在 field ,跟我们熟悉所Java的 this 指代当前类一样, field 指代当前参数,直接使用参数名 instance 代替不会报错但单例就没效果了
字符串问题
在Java中拼接字符串的代码可读性都很差,在Kotlin字符串拼接变得非常简洁,只需用 $ 后面加上参数名,复杂的参数要加上 {}
val pair = Pair(1, "one")
val (num, name) = pair
println("num = $num, name = $name")

输出num = 1, name = one
Java8新特性lambda的支持
lambda需要一个函数,但是又不想费神去命名一个函数的场合下使用,也就是指匿名函数。使用功能接口,把接口名、方法名和参数类型省掉不写再加个 -> 罢了。
使用Java开发Android时,处理监听回调是常见的事,kotlin可以直接编写监听回调而不用再通过匿名对象传递onClick方法,这个特性被称为Lambda表达式
view.setOnclickListener({
Toast.makeText(this, "Hello World!", Toast.LENGTH_LONG).show()
})

扩展函数
可以为任何已经存在的类添加新函数,相比传统工具类,扩展函数更具有可读性。
//为Fragment添加扩展函数
fun Fragment.toast(message: CharSequence, duration: Int = Toast.LENGTH_LONG){
Toast.makeText(getActivity(), message, duration).show()
}

调用时直接调用fragment.toast("Hello World!")或fragment.toast("Hello World!", 2000)
Kotlin中的参数与Java中有些不同。如你所见,我们先写参数的名字再写它的类型。上面调用的第二个参数(length)指定了一个默认值。这意味着你调用的时候可以传入第二个值或者不传,这样可以避免你需要的重载函数。
函数式支持(lambda),函数是一级公民
集合操作
  list转map(associateBy)
  场景:订单列表转换成以 id为key 的订单map
val mainOrders = orderDao!!.queryUserOrder(param)
val orderMap = mainOrders.associateBy { it.id }.toMap()

  map的key或者value转换
  假如一个map的key是String,需要转换成Long;或者map的value是一个对象,要转成另一个对象。按照标准Java写法,可以要new一个新的map,然后循环老的map,在kotlin中,一行代码搞定
val map = mutableMapOf(1 to 1, 2 to 2)
val newMap = map.mapKeys { "key_${it.key}" }.mapValues { "value_${it.value}" }
println(newMap)
//打印结果 {key_1=value_1, key_2=value_2}
val pair = Pair("ss","sg")
val map = mapOf(pair)
val map1=map.mapKeys { entry -> "${entry.value}!" }
for((key,value) in map1){
println("map1:key=$key")
println("map1:value=$value")
}
val map2 =map.mapKeys { (key, value) -> "$value" }
for((key,value) in map2){
println("map2:key=$key")
println("map2:value=$value")
}
val map3=map.mapValues { entry -> "${entry.value}!" }
for((key,value) in map3){
println("map3:key=$key")
println("map3:value=$value")
}
val map4=map.mapValues { (key, value) -> "$value" }
for((key,value) in map4){
println("map4:key=$key")
println("map4:value=$value")
}
打印结果:
map1:key=sg!
map1:value=sg
map2:key=sg
map2:value=sg
map3:key=ss
map3:value=sg!
map4:key=ss
map4:value=sg

参考文献  Kotlin for android Developers  kotlin 脚本练习转载自:https://www.cnblogs.com/vana/p/10201277.html 收起阅读 »

使用Kotlin开发第一个Android应用

直奔主题
第一步:为AndroidStudio安装Kotlin插件
在线安装步骤:File—>Settings—>Plugins—>Install JetBrains plugin…出现以下界面,选中Kotlin 点击右边的Install(因为我的已经安装了所以显示的是Update升级)

然后就是漫长的等待,安装完成后会提示重启AndroidStudio
由于本人在线安装没有成功,选择了离线安装。。。
离线安装步骤
首先去下载AndroidStudio用的Kotlin插件  分享一下我的插件下载地址:http://pan.baidu.com/s/1mij4ZHY
下载后还是File—>Settings—>Plugins—>Install plugin from disk…(注意最后选择Install plugin from disk…和在线安装时候选择的Install JetBrains plugin…不一样)选择你下载的插件的安装路径,点击OK如图:

 完成之后会提示重启重启后就可以了 (只是插件安装好了)
第二步:配置Kotlin 第一次创建Kotlin Activity,会提示 Kotlin not configured,我们直接点configure,如图:

 
点击Android with Gradle

点击OK

这时候我们的项目后发生以下的变化:
首先根目录的build.gradle文件:

首先app的build.gradle文件:

这时候说明你的Kotlin配置完成了 可以开发你的第一个Kotlin项目了
第三步:开发第一个Kotlin项目,首先要创建一个KotlinActivity

在KotlinActivity对应的xml文件中新建一个TextView

在KotlinActivity中使用:

要不要太简单啊我靠!!!!直接xml中的id名字.text就可以了!!!!
当输入tv_myTest会自动提示倒包的哦 Alt+Enter就可以了,就是这个包了:
 
不过我导入的时候遇到了问题 就是这个tv_myTest怎么也不提示  报错说没有这个变量。。。。。于是百度这个问题 找到了解决方法,就是在app的build.gradle文件中加一段代码
apply plugin: 'kotlin-android-extensions'加在哪呢?如图:

Sync Now一下 解决可以运行了 可以看到你的第一个用Kotlin编写的app了~(虽然简单的很。。。。)
补充一点:将原来的java文件转换为Kotlin文件,选中你的java文件,如下图操作:

 
 

 转载自:https://www.cnblogs.com/yunfang/p/7694118.html
继续阅读 »
直奔主题
第一步:为AndroidStudio安装Kotlin插件
在线安装步骤:File—>Settings—>Plugins—>Install JetBrains plugin…出现以下界面,选中Kotlin 点击右边的Install(因为我的已经安装了所以显示的是Update升级)

然后就是漫长的等待,安装完成后会提示重启AndroidStudio
由于本人在线安装没有成功,选择了离线安装。。。
离线安装步骤
首先去下载AndroidStudio用的Kotlin插件  分享一下我的插件下载地址:http://pan.baidu.com/s/1mij4ZHY
下载后还是File—>Settings—>Plugins—>Install plugin from disk…(注意最后选择Install plugin from disk…和在线安装时候选择的Install JetBrains plugin…不一样)选择你下载的插件的安装路径,点击OK如图:

 完成之后会提示重启重启后就可以了 (只是插件安装好了)
第二步:配置Kotlin 第一次创建Kotlin Activity,会提示 Kotlin not configured,我们直接点configure,如图:

 
点击Android with Gradle

点击OK

这时候我们的项目后发生以下的变化:
首先根目录的build.gradle文件:

首先app的build.gradle文件:

这时候说明你的Kotlin配置完成了 可以开发你的第一个Kotlin项目了
第三步:开发第一个Kotlin项目,首先要创建一个KotlinActivity

在KotlinActivity对应的xml文件中新建一个TextView

在KotlinActivity中使用:

要不要太简单啊我靠!!!!直接xml中的id名字.text就可以了!!!!
当输入tv_myTest会自动提示倒包的哦 Alt+Enter就可以了,就是这个包了:
 
不过我导入的时候遇到了问题 就是这个tv_myTest怎么也不提示  报错说没有这个变量。。。。。于是百度这个问题 找到了解决方法,就是在app的build.gradle文件中加一段代码
apply plugin: 'kotlin-android-extensions'加在哪呢?如图:

Sync Now一下 解决可以运行了 可以看到你的第一个用Kotlin编写的app了~(虽然简单的很。。。。)
补充一点:将原来的java文件转换为Kotlin文件,选中你的java文件,如下图操作:

 
 

 转载自:https://www.cnblogs.com/yunfang/p/7694118.html 收起阅读 »

Kotlin 资料

https://kotlinlang.org/docs/reference/  官方
https://github.com/JetBrains/kotlin/releases   Kotlin SDK
 
https://github.com/JetBrains/kotlin
Kotlin Programming Language
Welcome to Kotlin! Some handy links:

Kotlin Site
Getting Started Guide
Try Kotlin
Kotlin Standard Library
Issue Tracker
Forum
Kotlin Blog
Follow Kotlin on Twitter
Public Slack channel
TeamCity CI build

Editing Kotlin

Kotlin IntelliJ IDEA Plugin
Kotlin Eclipse Plugin
Kotlin Sublime Text Package

 
 
IDE工具:IntelliJ IDEA 社区版 或 Eclipse
1. IntelliJ IDEA
 
https://github.com/JetBrains/intellij-community
https://www.jetbrains.com/idea/
https://www.jetbrains.com/idea ... ndows
https://www.jetbrains.com/idea ... 3DIIC  跳转去下载
https://download.jetbrains.com ... 5.exe   exe下载
https://download.jetbrains.868 ... n.zip   zip包下载
 
 
延伸阅读:
IntelliJ IDEA版本:Ultimate、Community、EAP版本的区别
Community:
社区版,免费,但是功能有限制,Android Studio就是基于这个版本定制的。
http://idea-intellij.com/intellij-community/
Ultimate:
终极版,收费,功能无限制。
http://idea-intellij.com/intellij-ultimate/
EAP:
终极版的免费版,免费,功能无限制,但是每隔30天要重装一次。
http://idea-intellij.com/intellij-eap/

 
2. Google Kotlin
https://developer.android.com/kotlin/
 

 
3. 在 Android 开发中开始使用 Kotlin
https://developer.android.com/ ... otlin
Kotlin 在 Android Studio 3.0 及更高版本中完全受支持,因此,您可以轻松地使用 Kotlin 文件创建新项目,向现有项目中添加 Kotlin 文件以及将 Java 语言代码转换为 Kotlin 代码。然后,您可以使用 Android Studio 的所有现有工具处理 Kotlin 代码,例如自动填充、lint 检查、重构和调试等。
想要立即开始使用?请参阅我们的 Kotlin 示例。要详细了解 Kotlin 语言,请查看 Kotlin 学习资源。
将 Kotlin 添加到现有应用中
要掌握 Kotlin 使用技能并熟练使用 Kotlin,我们建议您采用渐进式方法:

首先用 Kotlin 编写测试。测试可用于检查代码回归性,并且在重构代码时更有把握。将现有 Java 代码转换为 Kotlin 代码时,测试特别有用。由于测试在打包过程中不会与应用捆绑在一起,因此它们是将 Kotlin 代码添加到代码库的安全位置。
用 Kotlin 编写新代码。在将现有 Java 代码转换为 Kotlin 代码之前,请尝试向应用添加一小段新的 Kotlin 代码。从小型类或顶级辅助函数开始。请务必在 Kotlin 代码中添加相关注释,以确保与 Java 代码的正确互操作性。

将现有代码更新为 Kotlin 代码。对编写新的 Kotlin 代码感到顺手后,您可以将现有的 Java 代码转换为 Kotlin 代码。不妨提取一小部分 Java 功能并转换为 Kotlin 类和顶级函数。
首先使用 Android Studio 代码转换器将 Java 文件中的代码转换为 Kotlin 代码。您还可以将从剪贴板粘贴的 Java 代码转换为 Kotlin 文件。
































Android API 和 Kotlin 示例
Kotlin 与 Java 语言可以完全互操作,因此调用 Android API 通常看起来与匹配的 Java 代码完全相同。但是现在,您可以将这些方法调用与 Kotlin 的语法功能相结合。
此外,我们正努力使所有 Android API 文档都包含惯用 Kotlin 参考。您可以在 Android 参考概览中找到指向可用 Kotlin 参考的链接。
下面是一些在 Kotlin 代码中调用 Android API 的示例(与采用 Java 语言的相同代码相对比):
声明 Activity
 


KOTLIN
















class MyActivity : AppCompatActivity() {  override fun onCreate(savedInstanceState: Bundle?) {    super.onCreate(savedInstanceState)    setContentView(R.layout.activity)  }}

 
创建点击监听器
 


KOTLIN

val fab = findViewById(R.id.fab) as FloatingActionButtonfab.setOnClickListener {  ...}

 
创建项目点击监听器
 


KOTLIN

private val mOnNavigationItemSelectedListener    = BottomNavigationView.OnNavigationItemSelectedListener { item ->  when (item.itemId) {    R.id.navigation_home -> {      mTextMessage.setText(R.string.title_home)      return@OnNavigationItemSelectedListener true    }    R.id.navigation_dashboard -> {      mTextMessage.setText(R.string.title_dashboard)      return@OnNavigationItemSelectedListener true    } } false}

 
最佳做法
当您能熟练使用 Kotlin 时,请尝试遵循以下准则:

侧重于可读性,而不是尽量缩短代码行。用 Kotlin 语法糖很容易过度。
最好确立最适合您团队的编码规范和惯用语。Kotlin 和 Android Kotlin 样式指南为确定 Kotlin 代码格式提供了很好的建议。

 
Kotlin编码规范:
https://kotlinlang.org/docs/re ... .html 官方编码规范
https://developer.android.com/kotlin/style-guide   Google Kotlin编码规范
 
4. Google Kotlin学习资源
https://developer.android.com/kotlin/resources
Kotlin 学习资源
Kotlin 是一种开源语言,它拥有自己的文档和社区,因此我们不在此处提供有关实际语言的文档。如果您是 Kotlin 新手,建议您查看以下资源。
文档和示例

在 Android 开发中开始使用 Kotlin:在 Android Studio 中开始使用 Kotlin 的简短指南。
Kotlin 示例:使用 Kotlin 构建的 Android 示例应用集合。
Kotlinlang.org:官方 Kotlin 网站。涵盖从指南到基本语法再到 Kotlin 标准库参考的所有内容。
Kotlin Koans Online:在线 IDE 中的一系列练习,可帮助您学习 Kotlin 语法。

视频

Udacity 课程:“面向程序员的 Kotlin 训练营”。由 Google 的 Kotlin 专家讲解的 Kotlin 编程语言基础知识。适用于 Java 或其他面向对象语言的程序员。
YouTube:搜索“Kotlin on Android”可搜到各种精彩的技术讲座。
O'Reilly 课程:Kotlin 课程“Kotlin 编程入门”时长 8 小时,由 JetBrains 开发者 Hadi Hariri 讲解。需要订阅;可以免费试订 10 天。
Treehouse 课程:“面向 Java 开发者的 Kotlin”讲授了 Kotlin,重点放在 Android 上。需要订阅;可以免费试订 7 天。
Udemy 课程:“面向初学者的 Kotlin”从零开始讲解了 Kotlin。需要订阅;新学员可享受折扣。

图书

Kotlin 实际应用:由 JetBrains 的 Kotlin 开发者 Dmitry Jemerov 和 Svetlana Isakova 撰写。
面向 Android 开发者的 Kotlin:由 Antonio Leiva 撰写。介绍 Kotlin 的首批图书之一。
通过 Kotlin 开发 Android 应用:由 Marcin Moskala 和 Igor Wojda 撰写。

Kotlin 网站上列出了更多图书。
 
https://www.manning.com/books/kotlin-in-action  Kotlin实际应用
 
5. Google Kotlin 案例
https://developer.android.com/ ... otlin
 
6. Kotlin upgrade
https://blog.jetbrains.com/kot ... -1-3/ 
How to upgrade
As always, you can try Kotlin online at play.kotl.in.

In Maven, Gradle and npm: Use 1.3.0 as the version number for the compiler and the standard library. See the docs here.
In IntelliJ IDEA: 2018.3 has Kotlin 1.3 bundled, in earlier versions Install or update the Kotlin plugin to version 1.3.
In Android Studio: Install or update the plugin through Plugin Manager.
In Eclipse: install the plugin using Marketplace.
The command-line compiler can be downloaded from the Github release page.

7. 在 Android 开发中使用 Kotlin 语言的常见问题解答
https://developer.android.com/kotlin/faq
Android 为何将 Kotlin 语言列为一级支持语言?
Kotlin 是一种与 Android 兼容的语言,它不仅语法简洁、更具表达性,还具备类型安全和空值安全的特性。它与 Java 语言可以无缝互通,热爱 Java 语言的开发者可以在继续使用 Java 语言的同时,逐步加入 Kotlin 代码并充分利用 Kotlin 库,轻松完成转换。此外,许多 Android 开发者已经发现 Kotlin 不仅可以提高开发速度,还能为编程带来更多乐趣,因此,我们希望为这些 Kotlin 用户提供更好的支持。您可以参阅此页,详细了解 Kotlin 和 Android。
 
我已经在使用 Kotlin 语言,有哪些变化值得关注?
短期内您将注意到的最大变化是:Android Studio 3.0 及以上版本中包含了经过全面测试的 Kotlin 支持工具。我们相信,这一变化将为您带来更加轻松、更加稳定的开发体验。
 
如何在 Android Studio 中使用 Kotlin?
Android Studio 3.0 及以上版本全面支持 Kotlin。以前,您需要添加 Kotlin 插件才能使用 Kotlin;而现在,所有新发布的 Android Studio 版本中都内置了这些工具。因此,您无需执行任何额外步骤,就可以直接使用 Kotlin 文件创建新项目,将 Java 语言代码转换成 Kotlin 代码,调试 Kotlin 代码,以及执行其他操作。详情请参阅“Kotlin 使用入门”。
 
如何在 Android Studio 中调试 Kotlin 代码?
Kotlin 代码的调试方法与 Java 代码相同。您不需要执行任何其他操作。
 
IDE 还为 Kotlin 提供其他哪些类型的支持(例如 Lint、自动填充、重构等)?
从 Android Studio 3.0 开始,我们的 IDE 已为 Kotlin 提供全面的工具支持。但是,目前还存在一些已知问题和限制,我们正在努力解决。
 
Kotlin 前景如何?
JetBrains 开发的 Kotlin 语言有着深思熟虑的设计理念,这是我们采纳该语言的原因之一。Google 正在与 JetBrains 开展合作,确保开发者在整个开发过程中(从语言到框架再到工具)都能获得出色的体验。此外,我们非常期待通过双方的努力,为 Kotlin 语言创建一个非盈利基金会以便进行后续的开发。
 
Kotlin 是开源语言吗?
Kotlin 的首选许可是 Apache Software License 2.0 版(“Apache 2.0”),Kotlin 软件的大部分内容都是根据 Apache 2.0 授权用户使用。尽管该项目将尽可能遵循此首选许可,但也可能存在将根据具体情况处理的例外情况。例如,Kotlin 使用的部分第三方依赖项可能使用不同的开放源代码许可,但这些许可与 Apache 2 许可并不冲突。
 
如何在 Java 和 Kotlin 语言之间做出选择?
您无需二选一!您可以根据需要同时使用两种语言。如果您需要了解 Kotlin 是否适合自己,您可以在 Android 开发中试用 Kotlin 语言,也可以参阅这些 Kotlin 资源,详细了解该语言
 
我可以在 Kotlin 中调用 Android 或其他 Java 语言库的 API 吗?
可以。Kotlin 与 Java 语言具有互操作性。此设计让 Kotlin 代码可以透明地调用 Java 语言方法;对于 Kotlin 独有的功能,可采用注释轻松向 Java 代码公开。对于未使用任何 Kotlin 特有语义的 Kotlin 文件,Java 代码可以直接引用,无需添加任何注释。两相结合,您就可以同时使用 Java 代码和 Kotlin 代码。有关详情,请参阅 Kotlin 互操作文档。
 
你们有 Android API 的 Kotlin 参考文档吗?
有!我们正努力使所有 Android API 文档都包含惯用 Kotlin 参考。它们尚未准备就绪,但您可以在 Android 参考概览中找到指向可用 Kotlin 参考的链接。如果您要寻找核心 Kotlin 语言参考,请转到 Kotlin 标准库参考。
 
我可以在同一个项目中同时使用 Java 文件和 Kotlin 文件吗?
可以。您可以根据自己的喜好或多或少采用 Kotlin 语言进行开发,然后利用 Kotlin 与 Java 的互操作性将 Kotlin 代码与 Java 代码结合在一起。
 
我可以在 Kotlin 代码中使用 C++ 代码吗?
可以,Kotlin 完全支持 JNI。您只需使用 external 修饰符标记 JNI 方法即可。
 
如何将 Kotlin 代码添加到我的新项目中?
当您在 Android Studio 中创建新项目时,只需选中 Include Kotlin support 复选框即可。有关详情,请参阅 Kotlin 使用入门。
 
如何将 Kotlin 代码添加到我的现有项目中?
在 Project 窗口中选择相应模块,然后依次选择 File > New,选择任意 Android 模板,然后将 Kotlin 选作 Source language。有关详情,请参阅 Kotlin 使用入门。
 
如何将 Java 语言代码转换成 Kotlin 代码?
打开 Java 文件,然后依次选择 Code > Convert Java File to Kotlin File。您也可以新建一个 Kotlin 文件 (File > New > Kotlin File/Class),然后将 Java 代码粘贴到此文件中。界面上出现提示时,点击 Yes,即可将 Java 代码转换成 Kotlin 代码。有关详情,请参阅 Kotlin 使用入门。
 
你们会提供有关 Kotlin 的配套文档、示例、codelab 和模板吗?
为了向 Java 和 Kotlin 语言用户尽可能提供最实用的帮助,我们正在努力完善我们的文档和教程资料。与此同时,开发者可以借助 Kotlin 与 Java 语言之间出色的互操作性,并利用相关功能在 Android Studio 中将 Java 语言代码自动转换成 Kotlin 代码。
 
Kotlin 在 Android 开发中能实现协程吗?能实现异步/等候吗?
Kotlin 协程目前应该可以实现,但这些特性还处于实验设计阶段。因此,Kotlin 不能保证它们未来的可用状态,Android 自然也无法做出承诺。
 
Kotlin 对 APK 大小/方法数有什么影响?
Kotlin 运行时会导致您的调试 APK 增加大约 7000 个方法和约 1MB 的大小。如果您使用 Kotlin 替换项目中的另一个库(例如 Guava 或 RxJava),净影响可能会减小。如果您像优化其他应用代码和库一样,使用 ProGuard 对 APK 进行发布前优化,APK 的大小也会减小。
 
使用 Kotlin 会影响性能吗?
使用 Kotlin 不会对性能产生直接影响,但就像使用 Java 语言一样,您应该精心考虑如何使用这种语言。例如,在新的集合实例间重复复制会影响 GC 性能,调用允许非空类型的方法会导致调用空值检查方法(当然,您可以在编译器中使用 -Xno-param-assertions 停用运行时空值检查)。
 
Kotlin 支持哪些 Android 版本?
所有版本都支持!Kotlin 与 JDK 6 兼容,因此使用 Kotlin 语言开发的应用可以在较早版本的 Android 上安全运行。
 
在哪里可以了解更多有关使用 Kotlin 的信息?
请参阅 Kotlin 学习资源。
 
8. Kotlin 和 Java交互
https://developer.android.com/kotlin/interop
 
9. 构建第一个
https://codelabs.developers.go ... l%230
 
 
 
参考:
https://www.cnblogs.com/Jetictors/p/7723018.html   Kotlin——初级篇(一):最详细的环境搭建
 转载自:https://www.cnblogs.com/onelikeone/p/9942164.html
继续阅读 »
https://kotlinlang.org/docs/reference/  官方
https://github.com/JetBrains/kotlin/releases   Kotlin SDK
 
https://github.com/JetBrains/kotlin
Kotlin Programming Language
Welcome to Kotlin! Some handy links:

Kotlin Site
Getting Started Guide
Try Kotlin
Kotlin Standard Library
Issue Tracker
Forum
Kotlin Blog
Follow Kotlin on Twitter
Public Slack channel
TeamCity CI build

Editing Kotlin

Kotlin IntelliJ IDEA Plugin
Kotlin Eclipse Plugin
Kotlin Sublime Text Package

 
 
IDE工具:IntelliJ IDEA 社区版 或 Eclipse
1. IntelliJ IDEA
 
https://github.com/JetBrains/intellij-community
https://www.jetbrains.com/idea/
https://www.jetbrains.com/idea ... ndows
https://www.jetbrains.com/idea ... 3DIIC  跳转去下载
https://download.jetbrains.com ... 5.exe   exe下载
https://download.jetbrains.868 ... n.zip   zip包下载
 
 
延伸阅读:
IntelliJ IDEA版本:Ultimate、Community、EAP版本的区别
Community:
社区版,免费,但是功能有限制,Android Studio就是基于这个版本定制的。
http://idea-intellij.com/intellij-community/
Ultimate:
终极版,收费,功能无限制。
http://idea-intellij.com/intellij-ultimate/
EAP:
终极版的免费版,免费,功能无限制,但是每隔30天要重装一次。
http://idea-intellij.com/intellij-eap/

 
2. Google Kotlin
https://developer.android.com/kotlin/
 

 
3. 在 Android 开发中开始使用 Kotlin
https://developer.android.com/ ... otlin
Kotlin 在 Android Studio 3.0 及更高版本中完全受支持,因此,您可以轻松地使用 Kotlin 文件创建新项目,向现有项目中添加 Kotlin 文件以及将 Java 语言代码转换为 Kotlin 代码。然后,您可以使用 Android Studio 的所有现有工具处理 Kotlin 代码,例如自动填充、lint 检查、重构和调试等。
想要立即开始使用?请参阅我们的 Kotlin 示例。要详细了解 Kotlin 语言,请查看 Kotlin 学习资源。
将 Kotlin 添加到现有应用中
要掌握 Kotlin 使用技能并熟练使用 Kotlin,我们建议您采用渐进式方法:

首先用 Kotlin 编写测试。测试可用于检查代码回归性,并且在重构代码时更有把握。将现有 Java 代码转换为 Kotlin 代码时,测试特别有用。由于测试在打包过程中不会与应用捆绑在一起,因此它们是将 Kotlin 代码添加到代码库的安全位置。
用 Kotlin 编写新代码。在将现有 Java 代码转换为 Kotlin 代码之前,请尝试向应用添加一小段新的 Kotlin 代码。从小型类或顶级辅助函数开始。请务必在 Kotlin 代码中添加相关注释,以确保与 Java 代码的正确互操作性。

将现有代码更新为 Kotlin 代码。对编写新的 Kotlin 代码感到顺手后,您可以将现有的 Java 代码转换为 Kotlin 代码。不妨提取一小部分 Java 功能并转换为 Kotlin 类和顶级函数。
首先使用 Android Studio 代码转换器将 Java 文件中的代码转换为 Kotlin 代码。您还可以将从剪贴板粘贴的 Java 代码转换为 Kotlin 文件。
































Android API 和 Kotlin 示例
Kotlin 与 Java 语言可以完全互操作,因此调用 Android API 通常看起来与匹配的 Java 代码完全相同。但是现在,您可以将这些方法调用与 Kotlin 的语法功能相结合。
此外,我们正努力使所有 Android API 文档都包含惯用 Kotlin 参考。您可以在 Android 参考概览中找到指向可用 Kotlin 参考的链接。
下面是一些在 Kotlin 代码中调用 Android API 的示例(与采用 Java 语言的相同代码相对比):
声明 Activity
 


KOTLIN
















class MyActivity : AppCompatActivity() {  override fun onCreate(savedInstanceState: Bundle?) {    super.onCreate(savedInstanceState)    setContentView(R.layout.activity)  }}

 
创建点击监听器
 


KOTLIN

val fab = findViewById(R.id.fab) as FloatingActionButtonfab.setOnClickListener {  ...}

 
创建项目点击监听器
 


KOTLIN

private val mOnNavigationItemSelectedListener    = BottomNavigationView.OnNavigationItemSelectedListener { item ->  when (item.itemId) {    R.id.navigation_home -> {      mTextMessage.setText(R.string.title_home)      return@OnNavigationItemSelectedListener true    }    R.id.navigation_dashboard -> {      mTextMessage.setText(R.string.title_dashboard)      return@OnNavigationItemSelectedListener true    } } false}

 
最佳做法
当您能熟练使用 Kotlin 时,请尝试遵循以下准则:

侧重于可读性,而不是尽量缩短代码行。用 Kotlin 语法糖很容易过度。
最好确立最适合您团队的编码规范和惯用语。Kotlin 和 Android Kotlin 样式指南为确定 Kotlin 代码格式提供了很好的建议。

 
Kotlin编码规范:
https://kotlinlang.org/docs/re ... .html 官方编码规范
https://developer.android.com/kotlin/style-guide   Google Kotlin编码规范
 
4. Google Kotlin学习资源
https://developer.android.com/kotlin/resources
Kotlin 学习资源
Kotlin 是一种开源语言,它拥有自己的文档和社区,因此我们不在此处提供有关实际语言的文档。如果您是 Kotlin 新手,建议您查看以下资源。
文档和示例

在 Android 开发中开始使用 Kotlin:在 Android Studio 中开始使用 Kotlin 的简短指南。
Kotlin 示例:使用 Kotlin 构建的 Android 示例应用集合。
Kotlinlang.org:官方 Kotlin 网站。涵盖从指南到基本语法再到 Kotlin 标准库参考的所有内容。
Kotlin Koans Online:在线 IDE 中的一系列练习,可帮助您学习 Kotlin 语法。

视频

Udacity 课程:“面向程序员的 Kotlin 训练营”。由 Google 的 Kotlin 专家讲解的 Kotlin 编程语言基础知识。适用于 Java 或其他面向对象语言的程序员。
YouTube:搜索“Kotlin on Android”可搜到各种精彩的技术讲座。
O'Reilly 课程:Kotlin 课程“Kotlin 编程入门”时长 8 小时,由 JetBrains 开发者 Hadi Hariri 讲解。需要订阅;可以免费试订 10 天。
Treehouse 课程:“面向 Java 开发者的 Kotlin”讲授了 Kotlin,重点放在 Android 上。需要订阅;可以免费试订 7 天。
Udemy 课程:“面向初学者的 Kotlin”从零开始讲解了 Kotlin。需要订阅;新学员可享受折扣。

图书

Kotlin 实际应用:由 JetBrains 的 Kotlin 开发者 Dmitry Jemerov 和 Svetlana Isakova 撰写。
面向 Android 开发者的 Kotlin:由 Antonio Leiva 撰写。介绍 Kotlin 的首批图书之一。
通过 Kotlin 开发 Android 应用:由 Marcin Moskala 和 Igor Wojda 撰写。

Kotlin 网站上列出了更多图书。
 
https://www.manning.com/books/kotlin-in-action  Kotlin实际应用
 
5. Google Kotlin 案例
https://developer.android.com/ ... otlin
 
6. Kotlin upgrade
https://blog.jetbrains.com/kot ... -1-3/ 
How to upgrade
As always, you can try Kotlin online at play.kotl.in.

In Maven, Gradle and npm: Use 1.3.0 as the version number for the compiler and the standard library. See the docs here.
In IntelliJ IDEA: 2018.3 has Kotlin 1.3 bundled, in earlier versions Install or update the Kotlin plugin to version 1.3.
In Android Studio: Install or update the plugin through Plugin Manager.
In Eclipse: install the plugin using Marketplace.
The command-line compiler can be downloaded from the Github release page.

7. 在 Android 开发中使用 Kotlin 语言的常见问题解答
https://developer.android.com/kotlin/faq
Android 为何将 Kotlin 语言列为一级支持语言?
Kotlin 是一种与 Android 兼容的语言,它不仅语法简洁、更具表达性,还具备类型安全和空值安全的特性。它与 Java 语言可以无缝互通,热爱 Java 语言的开发者可以在继续使用 Java 语言的同时,逐步加入 Kotlin 代码并充分利用 Kotlin 库,轻松完成转换。此外,许多 Android 开发者已经发现 Kotlin 不仅可以提高开发速度,还能为编程带来更多乐趣,因此,我们希望为这些 Kotlin 用户提供更好的支持。您可以参阅此页,详细了解 Kotlin 和 Android。
 
我已经在使用 Kotlin 语言,有哪些变化值得关注?
短期内您将注意到的最大变化是:Android Studio 3.0 及以上版本中包含了经过全面测试的 Kotlin 支持工具。我们相信,这一变化将为您带来更加轻松、更加稳定的开发体验。
 
如何在 Android Studio 中使用 Kotlin?
Android Studio 3.0 及以上版本全面支持 Kotlin。以前,您需要添加 Kotlin 插件才能使用 Kotlin;而现在,所有新发布的 Android Studio 版本中都内置了这些工具。因此,您无需执行任何额外步骤,就可以直接使用 Kotlin 文件创建新项目,将 Java 语言代码转换成 Kotlin 代码,调试 Kotlin 代码,以及执行其他操作。详情请参阅“Kotlin 使用入门”。
 
如何在 Android Studio 中调试 Kotlin 代码?
Kotlin 代码的调试方法与 Java 代码相同。您不需要执行任何其他操作。
 
IDE 还为 Kotlin 提供其他哪些类型的支持(例如 Lint、自动填充、重构等)?
从 Android Studio 3.0 开始,我们的 IDE 已为 Kotlin 提供全面的工具支持。但是,目前还存在一些已知问题和限制,我们正在努力解决。
 
Kotlin 前景如何?
JetBrains 开发的 Kotlin 语言有着深思熟虑的设计理念,这是我们采纳该语言的原因之一。Google 正在与 JetBrains 开展合作,确保开发者在整个开发过程中(从语言到框架再到工具)都能获得出色的体验。此外,我们非常期待通过双方的努力,为 Kotlin 语言创建一个非盈利基金会以便进行后续的开发。
 
Kotlin 是开源语言吗?
Kotlin 的首选许可是 Apache Software License 2.0 版(“Apache 2.0”),Kotlin 软件的大部分内容都是根据 Apache 2.0 授权用户使用。尽管该项目将尽可能遵循此首选许可,但也可能存在将根据具体情况处理的例外情况。例如,Kotlin 使用的部分第三方依赖项可能使用不同的开放源代码许可,但这些许可与 Apache 2 许可并不冲突。
 
如何在 Java 和 Kotlin 语言之间做出选择?
您无需二选一!您可以根据需要同时使用两种语言。如果您需要了解 Kotlin 是否适合自己,您可以在 Android 开发中试用 Kotlin 语言,也可以参阅这些 Kotlin 资源,详细了解该语言
 
我可以在 Kotlin 中调用 Android 或其他 Java 语言库的 API 吗?
可以。Kotlin 与 Java 语言具有互操作性。此设计让 Kotlin 代码可以透明地调用 Java 语言方法;对于 Kotlin 独有的功能,可采用注释轻松向 Java 代码公开。对于未使用任何 Kotlin 特有语义的 Kotlin 文件,Java 代码可以直接引用,无需添加任何注释。两相结合,您就可以同时使用 Java 代码和 Kotlin 代码。有关详情,请参阅 Kotlin 互操作文档。
 
你们有 Android API 的 Kotlin 参考文档吗?
有!我们正努力使所有 Android API 文档都包含惯用 Kotlin 参考。它们尚未准备就绪,但您可以在 Android 参考概览中找到指向可用 Kotlin 参考的链接。如果您要寻找核心 Kotlin 语言参考,请转到 Kotlin 标准库参考。
 
我可以在同一个项目中同时使用 Java 文件和 Kotlin 文件吗?
可以。您可以根据自己的喜好或多或少采用 Kotlin 语言进行开发,然后利用 Kotlin 与 Java 的互操作性将 Kotlin 代码与 Java 代码结合在一起。
 
我可以在 Kotlin 代码中使用 C++ 代码吗?
可以,Kotlin 完全支持 JNI。您只需使用 external 修饰符标记 JNI 方法即可。
 
如何将 Kotlin 代码添加到我的新项目中?
当您在 Android Studio 中创建新项目时,只需选中 Include Kotlin support 复选框即可。有关详情,请参阅 Kotlin 使用入门。
 
如何将 Kotlin 代码添加到我的现有项目中?
在 Project 窗口中选择相应模块,然后依次选择 File > New,选择任意 Android 模板,然后将 Kotlin 选作 Source language。有关详情,请参阅 Kotlin 使用入门。
 
如何将 Java 语言代码转换成 Kotlin 代码?
打开 Java 文件,然后依次选择 Code > Convert Java File to Kotlin File。您也可以新建一个 Kotlin 文件 (File > New > Kotlin File/Class),然后将 Java 代码粘贴到此文件中。界面上出现提示时,点击 Yes,即可将 Java 代码转换成 Kotlin 代码。有关详情,请参阅 Kotlin 使用入门。
 
你们会提供有关 Kotlin 的配套文档、示例、codelab 和模板吗?
为了向 Java 和 Kotlin 语言用户尽可能提供最实用的帮助,我们正在努力完善我们的文档和教程资料。与此同时,开发者可以借助 Kotlin 与 Java 语言之间出色的互操作性,并利用相关功能在 Android Studio 中将 Java 语言代码自动转换成 Kotlin 代码。
 
Kotlin 在 Android 开发中能实现协程吗?能实现异步/等候吗?
Kotlin 协程目前应该可以实现,但这些特性还处于实验设计阶段。因此,Kotlin 不能保证它们未来的可用状态,Android 自然也无法做出承诺。
 
Kotlin 对 APK 大小/方法数有什么影响?
Kotlin 运行时会导致您的调试 APK 增加大约 7000 个方法和约 1MB 的大小。如果您使用 Kotlin 替换项目中的另一个库(例如 Guava 或 RxJava),净影响可能会减小。如果您像优化其他应用代码和库一样,使用 ProGuard 对 APK 进行发布前优化,APK 的大小也会减小。
 
使用 Kotlin 会影响性能吗?
使用 Kotlin 不会对性能产生直接影响,但就像使用 Java 语言一样,您应该精心考虑如何使用这种语言。例如,在新的集合实例间重复复制会影响 GC 性能,调用允许非空类型的方法会导致调用空值检查方法(当然,您可以在编译器中使用 -Xno-param-assertions 停用运行时空值检查)。
 
Kotlin 支持哪些 Android 版本?
所有版本都支持!Kotlin 与 JDK 6 兼容,因此使用 Kotlin 语言开发的应用可以在较早版本的 Android 上安全运行。
 
在哪里可以了解更多有关使用 Kotlin 的信息?
请参阅 Kotlin 学习资源。
 
8. Kotlin 和 Java交互
https://developer.android.com/kotlin/interop
 
9. 构建第一个
https://codelabs.developers.go ... l%230
 
 
 
参考:
https://www.cnblogs.com/Jetictors/p/7723018.html   Kotlin——初级篇(一):最详细的环境搭建
 转载自:https://www.cnblogs.com/onelikeone/p/9942164.html 收起阅读 »

用kotlin方式打开《第一行代码:Android》之开发酷欧天气(1)

参考:《第一行代码:Android》第2版——郭霖
注1:本文为原创,例子可参考郭前辈著作:《第一行代码:Android》第2版,转载请注明出处!
注2:本文不赘述android开发的基本理论,不介绍入门知识,不介绍Android Studio基本安装,开门见山,直接使用kotlin改写郭前辈的《第一行代码:Android》中的部分例子,有机会的话自己做一些新例子出来!
注3:本文基本以kotlin语言作为Android开发,偶尔涉及java作为对比
注4:开发基于Android Studio 3.0,并且新建项目时勾选“support kotlin”
进入实战——开发酷欧天气(1)
本次博文,我将尝试使用kotlin语言对郭前辈的《第一行代码》中的最后那个实战项目“酷欧天气”进行重写
我将跳过需求分析阶段,开门见山,进入正题(代码),详见书本:p486

14.4 遍历全国省市县数据(原书p499)

原书中在遍历了省市县数据后,郭神使用了litepal将数据写入到了sqlite表中,由于时间问题,跳过此步,采用每次都重新访问网址获取数据!
省市县网址:http://guolin.tech/api/china/
配置gradle
gradle.build(Module: app)
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
compile 'com.android.support:appcompat-v7:25.3.1'
testCompile 'junit:junit:4.12'
compile 'org.jetbrains.anko:anko-sdk15:0.9'
compile 'org.jetbrains.anko:anko-support-v4:0.9'
compile 'org.jetbrains.anko:anko-appcompat-v7:0.9'
compile "com.google.code.gson:gson:2.7"
}
可以看到我们依然使用了anko类库,这个类库简直就是android上的jquery!
另外添加了Google的Gson类库,用于对在线获取的json数据转换
manifest
package="cn.cslg.weatherkotlin">

......




打开网络权限!
layout布局文件结构

红色框出来的表示本次博文中必须用到的布局,当然其他的xml后面也要用到
注:详细xml布局文件和代码参考原书即可,布局文件我是照搬的!或者跳到本文最后!
最后打开res>valus>styles.xml