Android快速转战Kotlin教程「建议收藏」

Android快速转战Kotlin教程「建议收藏」前言kotlin是啥?这里就不用多说了,想必看这篇文章的童鞋肯定是有所了解的。那么这篇文章你可以收获什么?答:本文主要通过本人如何从java转战到kotlin并应用在实际项目中的个人经历,给大家提供一些学习思路、学习方法以及一些学习资料和个人总结。前提:你的项目(包含个人项目)即将开始用到kotlin(没有项目作为依托你会缺少十足的动力,而且缺少应用场景乘热打铁那也…

大家好,又见面了,我是你们的朋友全栈君。

前言

kotlin是啥?这里就不用多说了,想必看这篇文章的童鞋肯定是有所了解的。

那么这篇文章你可以收获什么?

答:本文主要通过本人如何从java转战到kotlin并应用在实际项目中的个人经历,给大家提供一些学习思路、学习方法以及一些学习资料和个人总结。

前提:你的项目(包含个人项目)即将开始用到kotlin(没有项目作为依托你会缺少十足的动力,而且缺少应用场景乘热打铁那也是白学)
建议:建议没有切换kotlin的小伙伴快来转战kotlin吧!最近一段时间搞了kotlin之后发现写起来确实比java爽多了,语法非常精简,而且据统计现已有30%安卓项目使用了kotlin,所以小伙伴们行动起来吧,这必定是大势所趋,可千万别被淘汰了啊

入门

俗话说万事开头难,不过我们先把Kotlin语法学习一遍,你就会发现so easy,而且语言思想都是相通的

第一步:学习语法

当然是去官网学习喽:http://kotlinlang.org/docs/reference/

如下图:

Android快速转战Kotlin教程「建议收藏」

不过英文吃力的小伙伴可以去菜鸟教程网站学习

地址:http://www.runoob.com/kotlin/kotlin-tutorial.html

如下图:

Android快速转战Kotlin教程「建议收藏」

内容与官网一致。

不过不能光看,一定要写,就算照着抄也要多写,尽量在学习时候多和java语法做对比,会印象深刻。
如下图,本人的练习代码:

Android快速转战Kotlin教程「建议收藏」

第二步:对比学习

大家可以参考下面的链接进行学习:

from-java-to-kotlin : https://github.com/MindorksOpenSource/from-java-to-kotlin

from-java-to-kotlin中给出了我们常用的语法对比

如图:

Android快速转战Kotlin教程「建议收藏」

第三步:Demo练习

通过上面的学习我们此刻已经熟悉了kotlin的基本语法,可以来尝试写一个万年历的Demo。

1、新建工程

我们新建一个工程,点击Include kotlin support
如图:

Android快速转战Kotlin教程「建议收藏」

我们看一下Include kotlin support都帮我们做了什么事情

首先module中gradle文件

如图:

Android快速转战Kotlin教程「建议收藏」

比我们之前的工程多了下面两个引用和一个依赖:

// 使用Kotlin插件
apply plugin: 'kotlin-android'
// 使用Kotlin Android扩展插件
apply plugin: 'kotlin-android-extensions'

dependencies {
    //...
    //添加Kotlin 标准库
    compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
    //...
}

知识点: kotlin-android-extensions相当于DataBinding,同样的目的为了偷懒不用写findViewByIdAndroid 开发必备。

我们再看一下project中的gradle文件
如图:

比我们之前的工程多了Kotlin编译插件:

// 添加了Kotlin编译插件
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"

2、Demo说明

该项目使用MVP模式,里面用到了Retrofit2+RxJava2,然后使用了聚合的万年历接口,Demo非常简单便于初学者快速掌握。

Demo使用展示:

Android快速转战Kotlin教程「建议收藏」

工程目录结构如图:

Android快速转战Kotlin教程「建议收藏」

3、Activity

看下布局文件非常简单,我们可以在activity里面直接将控件的id当成变量来使用

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    ....">

    <DatePicker
        android:id="@+id/dataPicker"
        .... />

    <Button
        android:id="@+id/selectButton"
        .... />

    <TextView
        android:id="@+id/titleTextView"
        .... />

    <TextView
        android:id="@+id/contentTextView"
       ....
       />

</android.support.constraint.ConstraintLayout>
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    selectButton.setOnClickListener {
        titleTextView.visibility = View.GONE
        selectButton.visibility = View.GONE
        contentTextView.visibility = View.GONE
        dataPicker.visibility = View.VISIBLE
    }
    ....
    ....
}

注意:直接使用id作为变量的时候,要在Module的gradle里面加入扩展,才能使用,不然会报错

apply plugin: 'kotlin-android-extensions'

这个上面已经说过,我们创建工程的时候如果选中Include kotlin support怎会自动在gradle中生成。

4、Retrofit+RxJava

Retrofit结合RxJava能快捷的使用网络请求。

创建Service接口,Kotlin的类型是写在后面

interface RetrofitService {

    /**
     *  获取当天详细信息
     *  @param date 日期
     */
    @GET("calendar/day")
    fun calenderDay(
            @Query("date") date: String,
            @Query("key") key: String
    ): Observable<CalentarDayBean>

    /**
     *  获取近期假期
     *  @param date 日期
     */
    @GET("calendar/month")
    fun calenderMonth(
            @Query("date") date: String
    ): Observable<CalentarMonthBean>

    /**
     *  获取当年假期列表
     *  @param date 日期
     */
    @GET("calendar/year")
    fun calenderYear(
            @Query("date") date: String
    ): Observable<CalentarYearBean>
}

创建Retrofit,Kotlin的class并不支持static变量,所以需要使用companion object来声明static变量,其实这个变量也不是真正的static变量,而是一个伴生对象

伴生对象可以实现静态调用,通过类名.属性名或者类名.方法名进行调用

class RetrofitUtil {
    companion object {
        /**
         * 创建Retrofit
         */
        fun create(url: String): Retrofit {
            //日志显示级别
            val level: HttpLoggingInterceptor.Level = HttpLoggingInterceptor.Level.BODY
            //新建log拦截器
            val loggingInterceptor: HttpLoggingInterceptor = HttpLoggingInterceptor(HttpLoggingInterceptor.Logger {
                message -> Logger.e("OkHttp: " + message)
            })
            loggingInterceptor.level = level
            // okHttpClientBuilder
            val okHttpClientBuilder = OkHttpClient().newBuilder()

            okHttpClientBuilder.connectTimeout(60, TimeUnit.SECONDS)
            okHttpClientBuilder.readTimeout(10, TimeUnit.SECONDS)
            //OkHttp进行添加拦截器loggingInterceptor
            //okHttpClientBuilder.addInterceptor(loggingInterceptor)

            return Retrofit.Builder()
                    .baseUrl(url)
                    .client(okHttpClientBuilder.build())
                    .addConverterFactory(GsonConverterFactory.create())
                    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                    .build()
        }

        val retrofitService: RetrofitService = RetrofitUtil.getService(Constants.REQUEST_BASE_URL, RetrofitService::class.java)

        /**
         * 获取ServiceApi
         */
        fun <T> getService(url: String, service: Class<T>): T {
            return create(url).create(service)
        }
    }
}

通过伴生对象,结合Retrofit结合RxJava 我们直接就可以调用接口了

RetrofitUtil
    .retrofitService
    .calenderDay(date,"933dc930886c8c0717607f9f8bae0b48")
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe({ result ->
        view?.showDayCalentarData(result)
        Logger.e(result.toString())
    }, { error ->
        view?.showError(error.message.toString())
        Logger.e(error.message.toString())
    })

5、使用对象声明

在写项目的时候,一般会将常量统一写到一个类里面,然后设置静态变量,由于在Kotlin中不存在静态变量,所有就有对象声明的存在,对象声明比较常用的地方就是在这里,对象声明用Objcet关键字表示。

object Constants {

    val REQUEST_BASE_URL = "http://v.juhe.cn/"

    val KEY = "1be865c0e67e3"
}

使用的时候直接类名加.加变量名,如Constants.REQUEST_BASE_URL

6、使用数据类

Kotlin有专门的数据类,就是用data修饰的类
首先我们先看一下json数据:

{
	"reason":"Success",
	"result":{
		"data":{
			"date":"2018-4-4",
			"weekday":"星期三",
			"animalsYear":"狗",
			"suit":"订盟.纳采.冠笄.拆卸.修造.动土.安床.入殓.除服.成服.移柩.安葬.破土.启攒.造仓.",
			"avoid":"作灶.开光.嫁娶.开市.入宅.",
			"year-month":"2018-4",
			"lunar":"二月十九",
			"lunarYear":"戊戌年"
		}
	},
	"error_code":0
}

再来看一下我的数据类:

data class CalentarDayBean(
    val reason: String,
    val result: CalentarDayResult,
    val error_code: Int
)

data class CalentarDayResult(
        val data: CalentarDayData
)

data class CalentarDayData(
        val date: String,
        val weekday: String,
        val animalsYear: String,
        val suit: String,
        val avoid: String,
        val yearMonth: String,
        val holiday: String,
        val lunar: String,
        val lunarYear: String,
        val desc: String
)

就是如此方便

7、MVP

kotlin的MVP和java原理一模一样我先定义了IBaseModelIBaseView

IBaseModel

interface IBaseModel<T> {

    fun onDestroy()

    fun attachView(view: T)
}

IBaseView

interface IBaseView {

    fun showLoading()


    fun hideLoading()

    fun showMessage(message: String)

    fun killMyself()
}

然后完成ICalentarContract,这个类似合同类的接口把P和V的所有方法全部写在一起,看起来代码格外清楚

interface ICalentarContract {
    /**
     * 对于经常使用的关于UI的方法可以定义到IBaseView中,如显示隐藏进度条,和显示文字消息
     */
    interface View : IBaseView {
        fun showDayCalentarData(calentarDayBean: CalentarDayBean)
        fun showError(errorMsg: String)
    }

    /**
     * Model层定义接口,外部只需关心Model返回的数据,无需关心内部细节,如是否使用缓存
     */
    interface Model : IBaseModel<ICalentarContract.View> {
        fun getDayCalentarData(date: String)
    }
}

然后activity去实现ICalentarContract.View,presenter去实现ICalentarContract.Model

class CalentarDatePresenter : ICalentarContract.Model {
....
}
class MainActivity : AppCompatActivity(), ICalentarContract.View {
...
}

so easy~~~ 到这里我们的Demo就完成了,可以尽情玩乐。

项目地址:待上传。。。。。。。。。。。。。

好了,到这里我们基本掌握了Kotlin在安卓中的应用,那么接下来就需要去学习一下kotlin设计模式以及一些进阶知识~

进阶

一、Kotlin设计模式

本文只列出几个常用的设计模式

1、观察者模式( observer pattern )

Example

interface TextChangedListener {
    fun onTextChanged(newText: String)
}

class PrintingTextChangedListener : TextChangedListener {
    override fun onTextChanged(newText: String) = println("Text is changed to: $newText")
}

class TextView {

    var listener: TextChangedListener? = null

    var text: String by Delegates.observable("") { prop, old, new ->
        listener?.onTextChanged(new)
    }
}

Usage

val textView = TextView()
textView.listener = PrintingTextChangedListener()
textView.text = "Lorem ipsum"
textView.text = "dolor sit amet"

Output

Text is changed to: Lorem ipsum
Text is changed to: dolor sit amet

2、策略模式( strategy pattern )

Example

class Printer(val stringFormatterStrategy: (String) -> String) {
    fun printString(string: String) = println(stringFormatterStrategy.invoke(string))
}

val lowerCaseFormatter: (String) -> String = { it.toLowerCase() }

val upperCaseFormatter = { it: String -> it.toUpperCase() }

Usage

val lowerCasePrinter = Printer(lowerCaseFormatter)
lowerCasePrinter.printString("LOREM ipsum DOLOR sit amet")

val upperCasePrinter = Printer(upperCaseFormatter)
upperCasePrinter.printString("LOREM ipsum DOLOR sit amet")

val prefixPrinter = Printer({ "Prefix: " + it })
prefixPrinter.printString("LOREM ipsum DOLOR sit amet")

Output

lorem ipsum dolor sit amet
LOREM IPSUM DOLOR SIT AMET
Prefix: LOREM ipsum DOLOR sit amet

3、单例模式(singleton pattern)

Example

class Singletone private constructor() {
    init {
        println("Initializing with object: $this")
    }

    companion object {
        val getInstance =SingletonHolder.holder
    }

    private object SingletonHolder {
        val holder = Singletone()
    }

    fun print() = println("Printing with object: $this")
}

Usage

Singletone.getInstance.print()
Singletone.getInstance.print()

Output

Initializing with object: advance.Singletone@266474c2
Printing with object: advance.Singletone@266474c2
Printing with object: advance.Singletone@266474c2

4、工厂模式(Factory Method)

Example

interface Currency {
    val code: String
}

class Euro(override val code: String = "EUR") : Currency
class UnitedStatesDollar(override val code: String = "USD") : Currency

enum class Country {
    UnitedStates, Spain, UK, Greece
}

class CurrencyFactory {
    fun currencyForCountry(country: Country): Currency? {
        when (country) {
            Country.Spain, Country.Greece -> return Euro()
            Country.UnitedStates          -> return UnitedStatesDollar()
            else                          -> return null
        }
    }
}

Usage

val noCurrencyCode = "No Currency Code Available"

val greeceCode = CurrencyFactory().currencyForCountry(Country.Greece)?.code() ?: noCurrencyCode
println("Greece currency: $greeceCode")

val usCode = CurrencyFactory().currencyForCountry(Country.UnitedStates)?.code() ?: noCurrencyCode
println("US currency: $usCode")

val ukCode = CurrencyFactory().currencyForCountry(Country.UK)?.code() ?: noCurrencyCode
println("UK currency: $ukCode")

Output

Greece currency: EUR
US currency: USD
UK currency: No Currency Code Available

5、代理模式(Protection Proxy)

Example

interface File {
    fun read(name: String)
}

class NormalFile : File {
    override fun read(name: String) = println("Reading file: $name")
}

//Proxy:
class SecuredFile : File {
    val normalFile = NormalFile()
    var password: String = ""

    override fun read(name: String) {
        if (password == "secret") {
            println("Password is correct: $password")
            normalFile.read(name)
        } else {
            println("Incorrect password. Access denied!")
        }
    }
}

Usage

val securedFile = SecuredFile()
securedFile.read("readme.md")

securedFile.password = "secret"
securedFile.read("readme.md")

Output

Incorrect password. Access denied!
Password is correct: secret
Reading file: readme.md

6、建造者模式(builder pattern)

Example

// Let's assume that Dialog class is provided by external library.
// We have only access to Dialog public interface which cannot be changed.

class Dialog() {

    fun showTitle() = println("showing title")

    fun setTitle(text: String) = println("setting title text $text")

    fun setTitleColor(color: String) = println("setting title color $color")

    fun showMessage() = println("showing message")

    fun setMessage(text: String) = println("setting message $text")

    fun setMessageColor(color: String) = println("setting message color $color")

    fun showImage(bitmapBytes: ByteArray) = println("showing image with size ${bitmapBytes.size}")

    fun show() = println("showing dialog $this")
}

//Builder:
class DialogBuilder() {
    constructor(init: DialogBuilder.() -> Unit) : this() {
        init()
    }

    private var titleHolder: TextView? = null
    private var messageHolder: TextView? = null
    private var imageHolder: File? = null

    fun title(init: TextView.() -> Unit) {
        titleHolder = TextView().apply { init() }
    }

    fun message(init: TextView.() -> Unit) {
        messageHolder = TextView().apply { init() }
    }

    fun image(init: () -> File) {
        imageHolder = init()
    }

    fun build(): Dialog {
        val dialog = Dialog()

        titleHolder?.apply {
            dialog.setTitle(text)
            dialog.setTitleColor(color)
            dialog.showTitle()
        }

        messageHolder?.apply {
            dialog.setMessage(text)
            dialog.setMessageColor(color)
            dialog.showMessage()
        }

        imageHolder?.apply {
            dialog.showImage(readBytes())
        }

        return dialog
    }

    class TextView {
        var text: String = ""
        var color: String = "#00000"
    }
}

Usage

//Function that creates dialog builder and builds Dialog
fun dialog(init: DialogBuilder.() -> Unit): Dialog {
    return DialogBuilder(init).build()
}

val dialog: Dialog = dialog {
	title {
    	text = "Dialog Title"
    }
    message {
        text = "Dialog Message"
        color = "#333333"
    }
    image {
        File.createTempFile("image", "jpg")
    }
}

dialog.show()

Output

setting title text Dialog Title
setting title color #00000
showing title
setting message Dialog Message
setting message color #333333
showing message
showing image with size 0
showing dialog Dialog@5f184fc6

2、相关书籍

个人认为还是需要找一本书籍好好地阅读一遍,一下提供了相关书籍可以选择适合自己的。

NO.1

《Kotlin for Android Developers》

Android快速转战Kotlin教程「建议收藏」

Kotlin是编写Android应用程序的新官方语言,多亏了这本书,你很快就能写出代码。直奔主题,实用和完整的例子,它将在开发Android应用程序的同时展示你的语言。学习Kotlin并开始使用这个强大而现代的语言再次享受Android开发。

NO.2

《Kotlin开发快速入门与实战》

Android快速转战Kotlin教程「建议收藏」

学习本书之前不需要具备任何的计算机专业背景,任何有志于APP开发的读者都能利用本书从头学起。

资深软件开发工程师根据Kotlin最新版本撰写,系统讲解Kotlin开发技巧和项目实战。全书共分为7章,内容层次清晰,难度循序渐进。希望通过阅读本书,能够让你成为一个全栈工程师。

NO.3

《疯狂Kotlin讲义》

Android快速转战Kotlin教程「建议收藏」

本书尤其适合从Java转Kotlin的读者,对于没有Java功底的读者,可忽略“对比”部分,直接学习本书也可掌握Kotlin编程。

本书对Kotlin的解读十分系统、全面,超过Kotlin官方文档本身覆盖的内容。本书很多地方都会结合Java字节码进行深入解读,比如对Kotlin扩展的解读,对Kotlin主、次构造器的解读,这种解读目的不止于教会读者简单地掌握Kotlin的用法,而是力求让读者深入理解Kotlin,且更好地理解Java。

NO.4

《Kotlin实战》

Android快速转战Kotlin教程「建议收藏」

本书主要面向有一定Java 经验的开发者。

本书将从语言的基本特性开始,逐渐覆盖其更多的高级特性,尤其注重讲解如何将 Koltin 集成到已有 Java 工程实践及其背后的原理。本书分为两个部分。第一部分讲解如何开始使用 Kotlin 现有的库和API,包括基本语法、扩展函数和扩展属性、数据类和伴生对象、lambda 表达式,以及数据类型系统(着重讲解了可空性和集合的概念)。第二部分教你如何使用 Kotlin 构建自己的 API,以及一些深层次特性——约定和委托属性、高阶函数、泛型、注解和反射,以及领域特定语言的构建。

本书适合广大移动开发者及入门学习者,尤其是紧跟主流趋势的前沿探索者。

NO.5

《揭秘Kotlin编程原理》

Android快速转战Kotlin教程「建议收藏」

本书深入介绍Kotlin面向对象设计的语法特性及其背后的实现方式。

在本书中,读者不仅能清晰地了解Kotlin的语法、高级特性,还能真正地掌握Kotlin背后的实现机制和设计哲学,形成对Kotlin语言既直观、又深刻的认识——在此基础上,读者能准确、快速地上手实践,大大提升自己的移动开发能力。

Kotlin的这些特性和实现机制,可以帮助开发者扫清开发道路上的一些障碍,让开发变得更加简单!本书是一本值得拥有,能切实帮助读者加薪提职的好书!

项目

学习一门语言最快的方式就是看其如何在实际项目中运用,有了上面的基础和进阶,下面我们看一些开源项目:

1.Kotlin-for-Android-Developers(★1676)

Android快速转战Kotlin教程「建议收藏」

介绍:这个项目其实是Kotlin-for-Android-Developers这本书的配套代码,如果你是kotlin的初学者,那么这绝对是你学习kotlin的不二之选。项目通过一个天气的例子很好的展示了kotlin带来的强大功能,比如网络数据的请求,数据的缓存设计,数据库的操作,各种扩展函数的妙用等等。

地址:https://github.com/antoniolg/Kotlin-for-Android-Developers

2.Bandhook-Kotlin (★1494)

Android快速转战Kotlin教程「建议收藏」

介绍:Kotlin版本的音乐播放器,数据来源于LastFm。

地址:https://github.com/antoniolg/Bandhook-Kotlin

3.GankClient-Kotlin (★1216)

Android快速转战Kotlin教程「建议收藏」

介绍:gank.io kotlin实现的干货集中营Android客户端,风格采用了Material Design。

地址:https://github.com/githubwing/GankClient-Kotlin

4.PoiShuhui-Kotlin(★897)

Android快速转战Kotlin教程「建议收藏」

介绍:一个用Kotlin写的简单漫画APP。

地址:https://github.com/wuapnjie/PoiShuhui-Kotlin

5.Eyepetizer-in-Kotlin(★1167)

Android快速转战Kotlin教程「建议收藏」

介绍:Kotlin版本的Eyepetizer客户端

地址:https://github.com/LRH1993/Eyepetizer-in-Kotlin

6.Tucao(★792)

Android快速转战Kotlin教程「建议收藏」

介绍:Kotlin版本的吐槽客户端

地址:https://github.com/blackbbc/Tucao

资源

一、重要资源

Kotlin 官网

https://kotlinlang.org/docs/reference/

Kotlin 官方网站是学习 Kotlin 好去处。在参考部分,你可以找到该语言的所有概念和功能的深入解析文档。在教程部分有关于设置工作环境并使用编译器的实用分步指南。

这里还有个 Kotlin 编译器,是一个浏览器 APP,你可以在上面尝试使用这门语言。它能加载许多示例,包括 Koans 课程 — 这是目前熟悉 Kotlin 语法的最好方式。

Kotlin 官博

https://blog.jetbrains.com/kotlin/

Kotlin 的官方博客由 JetBrains 的一位作者负责。你可以在这里找到所有与 Kotlin 相关的新闻、更新、教程、使用技巧等的内容。

在 Android 上开始使用 Kotlin

https://developer.android.com/kotlin/get-started.html

一篇很牛叉的文章,向我们展示了如何使用 Kotlin 编写和运行 Android 应用程序的测试

从 Java 到 Kotlin

https://github.com/MindorksOpenSource/from-java-to-kotlin

实用的快速提醒列表工具包含了一些简短的代码块,藉由这个来帮助你快速找到通用 Java 操作符、功能以及声明的 Kotlin 替代方案。

Kotlin 教学插件

https://blog.jetbrains.com/kotlin/2016/03/kotlin-educational-plugin/

用于 IntelliJ IDEa 的插件,可让你在本地离线环境下使用 Koans 课程。

Kotlin on GitHub

https://github.com/jetbrains/kotlin

Kotlin 于 2012 年开源,你可以对该语言进行贡献。

Kotlin Android 模板

https://github.com/nekocode/Kotlin-Android-Template

Android 项目模板,使其非常容易设置稳定的 Kotlin 工作区,并快速引导你开发应用程序。

不可错过的 Kotlin 资源列表

https://github.com/KotlinBy/awesome-kotlin

这是一个比较完整的 Kotlin 资源列表,包括各种实用链接、书籍、库、框架和视频等。该列表的组织结构非常好,kotlin.link 也提供了一个风格化的版本。

kotlin设计模式

https://github.com/dbacinski/Design-Patterns-In-Kotlin

DariuszBaciński 创建了一个 GitHub repo,其中有在 Kotlin 中实现的常见设计模式,也有用其他语言编写的类似项目,包括 Java,Swift,Java 和 PHP,如果你是其中一项语言的使用者,可以用它们作为参考点。

二、视频资源

Kotlin 介绍

https://www.youtube.com/watch?v=X1RVYt2QKQE

来自 Google I / O 2017 的演讲,大会首次向人们介绍 Kotlin,并提出了改进工作流程的想法。它涵盖了许多基础知识,并展示了一些很酷的 Kotlin 技巧。

明日胜于今,我用 Kotlin

https://www.youtube.com/watch?v=fPzxfeDJDzY

Google I / O 2017 大会关于 Kotlin 的第二个演讲。这个演讲涵盖了更多高级话题,如设计模式,最佳实践和其他常见规则。 演讲也揭示了在生产中使用 Kotlin 的意义,以及在工作中采用新兴语言将面临的挑战。

Peter Sommerhoff 教你学 Kotlin

https://www.youtube.com/playlist?list=PLpg00ti3ApRweIhdOI4VCFFStx4uXC__u

这是一个免费的 Kotlin 课程,适合初学者,前面介绍了从变量到条件循环和函数的所有基础知识,后面会深入到更高级的主题,如 Kotlin 中的面向对象以及像 lambda 表达式的功能编程。

使用 Kotlin&Gradle 更好地开发 Android

https://www.youtube.com/watch?v=_DaZQ374Chc

这个讲座从 2016 年开始,它介绍了现实世界中的编程语言功能,你将了解到 Kotlin 是如何适应 Android 工作流程中存在的工具。

使用 Kotlin&Gradle 更好地开发 Android

https://www.youtube.com/watch?v=ZlQhmkp_jyk

一个 8 分钟的浓缩教程,让你快速了解 Kotlin 的主要功能,如变量声明、Lambdas、扩展功能等等。

Jake Wharton:用 Kotlin 进行 Android 开发

https://www.youtube.com/watch?v=A2LukgT2mKc&t

关于 Kotlin 的介绍,演讲向我们解释了新语言是如何改进 Android 生态系统的,并展示了许多炫酷的方式,我们可以使用智能的 Kotlin 语法来获得优势。
Android快速转战Kotlin教程「建议收藏」

扫码关注公众号“伟大程序猿的诞生“,更多干货新鲜文章等着你~
Android快速转战Kotlin教程「建议收藏」
公众号回复“资料获取”,获取更多干货哦~

有问题添加本人微信号“fenghuokeji996” 或扫描博客导航栏本人二维码

我的博客即将同步至腾讯云+社区,邀请大家一同入驻:
https://cloud.tencent.com/developer/support-plan?invite_code=ncnq0hloo5yw

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/141760.html原文链接:https://javaforall.net

(0)
上一篇 2022年5月25日 上午8:40
下一篇 2022年5月25日 上午9:00


相关推荐

  • html5 scrollheight,JavaScript之scrollTop、scrollHeight、offsetTop、offsetHeight等属性学习笔记…[通俗易懂]

    html5 scrollheight,JavaScript之scrollTop、scrollHeight、offsetTop、offsetHeight等属性学习笔记…[通俗易懂]全文参考:https://github.com/iuap-design/blog/issues/38、MDNclientHeight,只读clientHeight可以用公式CSSheight+CSSpadding-水平滚动条的高度(如果存在)来计算。如图,这样一个div,它的clientHeight为95,计算:50(height)+30(padding-top)+30(pad…

    2022年7月23日
    13
  • Java————错误:找不到或无法加载主类

    Java————错误:找不到或无法加载主类小编表示 WTF 为什么找不到主类 dictionary2 0 找不到是什么原因 1 可能是编译的时候后缀带了 class 把后缀去掉 2 可能是因为你的 java 文件带了 package 包 但是你还在 java 文件所在目录运行 返回包的前一目录进行运行 小编就是因为 java 文件里带了 packageword project2 0 导致的错误 错误原因是 我们在包里运行文

    2026年3月20日
    2
  • Java数组插入或删除元素

    Java数组插入或删除元素Java数组常见操作练习Java数组插入或删除元素**练习1.随机生成一个整数型数组(1-10数组长度随机,0-50数组元素随机)在其数组的最后追加一个1-50随机数值**publicclassArrayInsert1{publicstaticvoidmain(String[]args){int[]arr=genArray();…

    2022年7月16日
    18
  • springboot的自动化配置是什么_spring三种配置方式

    springboot的自动化配置是什么_spring三种配置方式一、什么是SpringBoot的自动配置?SpringBoot的最大的特点就是简化了各种xml配置内容,还记得曾经使用SSM框架时我们在spring-mybatis.xml配置了多少内容吗?数据源、连接池、会话工厂、事务管理···,而现在SpringBoot告诉你这些都不需要了,一切交给它的自动配置吧!所以现在能大概明白什么是SpringBoot的自动配置了吗?简单来说就是用注解来对一些常规的配置做默认配置,简化xml配置内容,使你的项目能够快速运行。是否对SpringBoot自动配置

    2022年8月22日
    11
  • Python day2 知识回顾

    Python day2 知识回顾标准库一般放在 lib site packages 放自己下载的 起的 py 文件名称不要和模块名字相同 importsys print sys path 打印去哪里寻找这些模块的路径 print sys argv 当前路径打印 importoscmd res os system dir 只是打印目录输出在屏幕 但不保存 cmd res os popen dir read

    2026年3月16日
    2
  • Linux 下如何进入 MySQL 命令行

    Linux 下如何进入 MySQL 命令行格式:mysql-h主机地址-u用户名-p用户密码1、例1:连接到本机上的MYSQL一般可以直接键入命令mysql-uroot-p,回车后提示你输密码,如果刚安装好MYSQL,超级用户root是没有密码的,故直接回车即可进入到MYSQL中了,MYSQL的提示符是:mysql>2、连接到远程主机上的MySQL假设远程主机的IP为:10.0.0.1,用户名为root,密码为123。则键入以下命

    2022年6月3日
    59

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号