kotlin核心编程
我们的Android开发人员在语言限制方面遇到困难。 如您所知,当前的Android开发仅支持Java 6 (对Java 7进行了一些小的改进),因此我们每天都需要使用一种非常古老的语言来处理代码,这会降低生产力并迫使我们编写大量的样板代码和易碎的代码,很难读取维护。
希望最终,我们可以在Java虚拟机上运行,因此从技术上讲,可以在JVM中运行的任何内容都易于被用于开发Android Apps。 有很多语言可以生成JVM可以执行的字节码,因此,如今有一些替代方法开始流行,而Kotlin就是其中一种。
什么是Kotlin?
Kotlin是一种在JVM上运行的语言。 它由Jetbrains创建, Jetbrains是公司背后的强大工具,例如IntelliJ,这是Java开发人员最著名的IDE之一。
Kotlin是一种非常简单的语言。 它的主要目标之一是提供一种功能强大且具有简单且简化的语法的语言。 它的一些功能是:
- 它是轻量级的:这一点对于Android非常重要。 我们需要添加到项目中的库尽可能小。 在Android中,我们对方法数量有严格的限制,而Kotlin仅增加了大约6000种额外方法。
- 它具有互操作性:Kotlin能够与Java语言无缝通信。 这意味着我们可以在Kotlin代码中使用任何现有的Java库,因此即使该语言很年轻,我们也已经可以使用成千上万个库。 此外,还可以从Java代码中使用Kotlin代码,这意味着我们可以创建使用两种语言的软件。 您可以开始在Kotlin中编写新功能,并在Java中保留其余代码库。
- 这是一种强类型的语言:尽管您几乎不需要在整个代码中指定任何类型,因为编译器能够在几乎每种情况下推断变量的类型或函数的返回类型。 因此,您可以两全其美:简洁而安全的语言。
- 这是零安全的:Java的最大问题之一是零。 您无法指定变量或参数何时可以为null,因此会发生很多
NullPointerException
,并且在编码时很难检测到它们。 Kotlin使用显式无效性,这将迫使我们在必要时检查null。
Kotlin当前是1.0.0 Beta 3版本,但很快就会有最终版本。 无论如何,它已经为生产做好了准备,已经有许多公司成功使用它。
为什么Kotlin非常适合Android?
基本上是因为其所有功能都非常适合Android生态系统。 该库足够小,可以让我们在开发过程中不加维护。 它的大小相当于support-v4
库,并且在几乎每个更大的项目中我们都使用其他库。
此外,Android Studio(官方的Android IDE)是基于IntelliJ构建的。 这意味着我们的IDE可以很好地支持使用这种语言。 我们可以在几秒钟内配置我们的项目,并像往常一样继续使用IDE。 我们可以继续使用Gradle以及IDE提供的所有运行和调试功能。 从字面上看,它与用Java编写应用程序相同。
显然,由于其互操作性,我们可以使用Kotlin代码没有任何问题的Android SDK 。 实际上,SDK的某些部分甚至更易于使用,因为互操作性是智能的,例如,它将getter和setter映射到Kotlin属性,或者让我们将侦听器编写为闭包。
如何在Android中开始使用Kotlin
真的很简单。 只需按照以下步骤操作:
- 从IDE插件部分下载Kotlin插件
- 在您的模块中创建Kotlin类
- 使用操作“在项目中配置Kotlin ...”
- 请享用
一些功能
Kotlin具有许多很棒的功能,我今天将无法在这里进行解释。 如果您想继续学习,可以查看我的博客并阅读我的书。 但是今天我将解释一些有趣的东西,希望它能使您想要更多。
空安全
如前所述,Kotlin是空安全的。 如果类型可以为null,则需要通过设置?
来指定它?
类型之后。 从那时起,每次我们想要使用使用该类型的变量时,都需要检查无效性。
例如,此代码将无法编译:
var artist: Artist? = null
artist.print()
第二行将显示错误,因为未检查无效性。 我们可以做这样的事情:
if (artist != null) {
artist.print()
}
这显示了Kotlin的另一个出色功能:智能铸造。 如果我们检查了变量的类型,则无需将其强制转换为检查范围。 因此,我们现在可以在if
内使用artist
作为类型为Artist
变量。 这可以与我们执行的任何其他检查一起使用(例如在检查实例类型之后)。
通过使用?
,我们有一种更简单的方法来检查无效性?
在调用对象的函数之前。 我们甚至可以使用Elvis运算符?:
提供替代方法?:
val name = artist?.name ?: ""
资料类别
在Java中,如果我们想创建一个数据类或POJO类(一个只保存一些状态的类),则需要创建一个具有很多字段,getter和setter的类,可能还有一个toString
和equals
类:
public class Artist {
private long id;
private String name;
private String url;
private String mbid;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getMbid() {
return mbid;
}
public void setMbid(String mbid) {
this.mbid = mbid;
}
@Override public String toString() {
return "Artist{" +
"id=" + id +
", name='" + name + '\'' +
", url='" + url + '\'' +
", mbid='" + mbid + '\'' +
'}';
}
}
在Kotlin中,所有以前的代码都可以替换为:
data class Artist (
var id: Long,
var name: String,
var url: String,
var mbid: String)
Kotlin使用属性而不是字段。 属性本质上是一个字段加上其getter和setter 。 我们可以直接在构造函数中声明这些属性,您可以看到它们是在类名称之后定义的,如果不修改条目值,可以节省一些行。
data
修饰符提供了一些额外的功能:可读的toString()
,基于构造函数中定义的属性的equals()
, copy
函数,甚至是使我们将对象拆分为变量的一组组component
函数。 像这样:
val (id, name, url, mbid) = artist
互通性
我们拥有一些出色的互操作性功能,这些功能在Android中大有帮助。 其中之一是使用单一方法将接口映射到lambda 。 因此,这样的点击监听器:
view.setOnClickListener(object : View.OnClickListener {
override fun onClick(v: View) {
toast("Click")
}
})
可以转换成这样:
view.setOnClickListener { toast("Click") }
此外, getter和setter会自动映射到properties 。 这不会增加任何开销,因为字节码实际上只会调用原始的getter和setter。 这些是一些示例:
supportActionBar.title = title
textView.text = title
contactsList.adapter = ContactsAdapter()
Lambdas
Lambda可以节省大量代码,但重要的是,它可以让我们做一些没有它们就不可能(或太冗长)的事情。 有了他们,我们可以开始以更实用的方式进行思考。 Lambda只是指定一种定义函数的类型的方法。 例如,我们可以定义一个这样的变量:
val listener: (View) -> Boolean
这是一个能够声明一个函数的变量,该函数接收一个视图并返回一个函数。 闭包是我们必须定义函数将执行的方式:
val listener = { view: View -> view is TextView }
如果该视图是TextView
的实例,则先前的函数将获取View
并返回true
。 如果编译器能够推断类型,则无需指定它。 如果需要的话,我们可以更加明确:
val listener: (View) -> Boolean = { view -> view is TextView }
使用lambda,我们可以防止使用回调接口。 我们可以只设置要在操作完成后调用的函数:
fun asyncOperation(value: Int, callback: (Boolean) -> Unit) {
...
callback(true)
}
asyncOperation(5) { result -> println("result: $result") }
但是,还有一个更简单的选择,因为如果一个函数只有一个参数,我们可以使用保留字it
:
asyncOperation(5) { println("result: $it") }
馆藏
Kotlin中的收藏功能非常强大。 它们是通过Java集合编写的,因此这意味着当我们从任何Java库(例如Android SDK)获得结果时,我们仍然可以使用Kotlin提供的所有功能。
我们提供的可用收藏有:
- 可迭代的
- 采集
- 清单
- 组
- 地图
我们可以对它们执行很多操作。 这些是其中的一些:
- 过滤
- 分类
- 地图
- 压缩
- dropWhile
- 第一
- firstOrNull
- 持续
- lastOrNull
- 折…
您可能会在本文中看到完整的操作集。 因此,可以非常明确地定义一个复杂的操作,例如过滤器,排序和转换:
parsedContacts
.filter { it.name != null && it.image != null }
.sortedBy { it.name }
.map { Contact(it.id, it.name!!, it.image!!) }
我们可以通过一种简单的方式定义新的不可变列表:
val list = listOf(1, 2, 3, 4, 5)
或者,如果我们希望它是可变的(可以添加和删除项目),我们有一种很好的方式来访问和修改项目,就像对数组一样:
mutableList[0] = 1
val first = mutableList[0]
对于地图也是如此:
map["key"] = 1
val value = map["key"]
这是可能的,因为在实现我们自己的类时,我们可以重载一些基本的运算符。
扩展功能
扩展功能将使我们向无法修改的类添加额外的行为,因为它们属于例如库或SDK。
我们可以为ViewGroup
类创建一个inflate()
函数:
fun ViewGroup.inflate(layoutRes: Int): View {
return LayoutInflater.from(context).inflate(layoutRes, this, false)
}
从现在开始,我们可以将其用作任何其他方法:
val v = parent.inflate(R.layout.view_item)
甚至是ImageView
的loadUrl
函数。 我们可以在函数内部使用Picasso库:
fun ImageView.loadUrl(url: String) {
Picasso.with(context).load(url).into(this)
}
所有ImageView
现在都可以使用此功能:
contactImage.loadUrl(contact.imageUrl)
接口
Kotlin中的接口可以包含代码,该代码模拟简单的多重继承。 一个类可以由许多类的代码组成,而不仅仅是父类。 但是,接口无法保持状态。 因此,如果我们在接口中定义属性,则实现该属性的类必须重写该属性并提供一个值。
一个示例可能是将处理Toolbar
的ToolbarManager
类:
interface ToolbarManager {
val toolbar: Toolbar
fun initToolbar() {
toolbar.inflateMenu(R.menu.menu_main)
toolbar.setOnMenuItemClickListener {
when (it.itemId) {
R.id.action_settings -> App.instance.toast("Settings")
else -> App.instance.toast("Unknown option")
}
true
}
}
}
使用Toolbar
所有活动或片段均可使用此界面:
class MainActivity : AppCompatActivity(), ToolbarManager {
override val toolbar by lazy { find<Toolbar>(R.id.toolbar) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
initToolbar()
...
}
}
当表达
When
可以用Java switch
,但是功能更强大。 它可以从字面上检查任何内容。 一个简单的例子:
val cost = when(x) {
in 1..10 -> "cheap"
in 10..100 -> "regular"
in 100..1000 -> "expensive"
in specialValues -> "special value!"
else -> "not rated"
}
我们可以检查数字是否在范围内,甚至在集合内( specialValues
是列表)。 但是,如果不将参数设置为when
,则只需检查所需内容即可。 像这样可能疯狂的事情:
val res = when {
x in 1..10 -> "cheap"
s.contains("hello") -> "it's a welcome!"
v is ViewGroup -> "child count: ${v.getChildCount()}"
else -> ""
}
Kotlin Android扩展
Kotlin团队为Android开发人员提供的另一种工具。 它将能够读取XML并将一组属性注入到活动,片段或视图中,并将布局内部的视图转换为正确的类型。
如果我们有这样的布局:
<FrameLayout
xmlns:android="..."
android:id="@+id/frameLayout"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/welcomeText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</FrameLayout>
我们只需要添加以下合成导入:
import kotlinx.android.synthetic.main.*
从那一刻起,我们可以在Activity
使用视图:
override fun onCreate(savedInstanceState: Bundle?) {
super<BaseActivity>.onCreate(savedInstanceState)
setContentView(R.id.main)
frameLayout.setVisibility(View.VISIBLE)
welcomeText.setText("I´m a welcome text!!")
}
就这么简单。
安科
Anko是Kotlin团队正在开发的用于简化Android开发的库。 它的主要目标是提供DSL以使用Kotlin代码声明视图:
verticalLayout {
val name = editText()
button("Say Hello") {
onClick { toast("Hello, ${name.text}!") }
}
}
但是它还包括许多其他有用的东西。 例如,导航到其他活动的好方法:
startActivity<DetailActivity>("id" to res.id, "name" to res.name)
它仅收到一组Pair
,并在创建用于导航到活动的意图(指定为函数的类型)时将其添加到包中。
我们还可以直接访问系统服务:
context.layoutInflater
context.notificationManager
context.sensorManager
context.vibrator
或创建敬酒和警报的简单方法:
toast(R.string.message)
longToast("Wow, such a duration")
alert("Yes /no Alert") {
positiveButton("Yes") { submit() }
negativeButton("No") {}
}.show()
我喜欢的一个简单的简单DSL可以处理异步问题:
async {
val result = longRequest()
uiThread { bindForecast(result) }
}
它还提供了一组使用SQLite和游标的工具。 ManagedSQLiteOpenHelper
提供了一种use
方法,该方法将接收数据库并可以直接调用其功能:
dbHelper.use {
select("TABLE_NAME").where("_id = {id}", "id" to 20)
}
如您所见,它具有不错的select
DSL,但还有一个简单的create
功能:
db.createTable("TABLE_NAME", true,
"_id" to INTEGER + PRIMARY_KEY,
"name" to TEXT)
处理游标时,可以使用一些扩展功能,例如parseList
, parseOpt
或parseClass
,这些功能将有助于解析结果。
结论
如您所见,Kotlin在许多方面简化了Android开发。 这将提高您的生产率,并使您以非常不同和更简单的方式解决常见问题。
我的建议是您至少尝试一下并尝试一下。 这是一种非常有趣的语言,非常容易学习。 如果您认为该语言适合您,则可以阅读Kotlin for Android Developers book继续学习它。
翻译自: https://www.javacodegeeks.com/2015/12/kotlin-android-developers.html
kotlin核心编程