原文链接 : Kotlin awesome tricks for Android
我已经在这个Blog里讨论了很多Kotlin了,现在Google也正在讨论Kotlin,Kotlin 1.0 RC 已经发布了,毫无疑问,Kotlin不仅仅是Android的一个替代选择。Kotlin就在这里,我推荐你开始学习它。
这里已经有一些信息了,但是如果你想要真正的关注和快速学习,我推荐你这些资源:
Kotlin reference:如果你想深入了解这个语言的细节,这里是你能找到的最好的地方。我所知道关于这个语言的最好参考文献之一。
This blog:这个链接是我整理的所有关于Kotlin的文章的地方。你不应该错过它,文章属于初级和中级。
Kotlin for Android Developers, The book:如果你想快速和持续的学习,这本书是最好的方法。如果你已经了解了Andriod,这将是一个在你的项目中使用kotlin的快速途径。我已经编写很长一段时间了,当新版本发布的时候我就会更新它。已经更新到了Kotlin 1.0 RC。除此之外如果你订阅了这个列表,你将收到免费的头5个章节和这本书末尾显示的一个购买折扣。
在我要讲解之前,有一个要说明的是Kotlin能给你带来简化的Android代码。这里有一组没有特定顺序的独立的例子。
Java 7上编写监听和回调事件非常繁琐的原因是缺少了lambdas。Kotlin有非常好的lambdas和与Java库有非常好的兼容性。用lambda一个方法即可映射接口。你可以这么做:
myButton.setOnClickListener { navigateToDetail() }
这就是所有。
当你在Adapter中实例化时,你需要inflate一个layout,你会这样写:
LayoutInflater.from(parent.getContext()).inflate(R.id.my_layout, parent, false);
为什么父类不能inflate它自己的layout?好了,用Kotlin你可以。可以创建一个扩展的方法为你所用:
fun ViewGroup.inflate(@LayoutRes layoutRes: Int, attachToRoot: Boolean = false): View {
return LayoutInflater.from(context).inflate(layoutRes, this, attachToRoot)
}
ViewGroup
现在有了一个新的inflate
方法,接受参数是一个layout资源和可选的attachToRoot
。通过传入不同的值,你可以创建同一个函数的很多不同版本,但不需要重载函数。现在可以这么做:
parent.inflate(R.layout.my_layout)
parent.inflate(R.layout.my_layout, true)
ImageView
不能直接从网络上加载图片。我们有一些创建自定义view的库,比如:NetworkImageView
,但这要求你使用继承,有时这会导致问题。现在我们知道我们可以在任何类上添加函数了,为什么不这样做呢?
fun ImageView.loadUrl(url: String) {
Picasso.with(context).load(url).into(this)
}
现在你可以使用这个函数了,但神奇的是这个函数的本身。你现在有超级类ImageView
:
imageView.loadUrl("http://....")
很好。
当重写onOptionsItemSelected
时,我们通常创建一个设置好分支的switch
,一般都返回true,最后都调用super。如果在这些action中有drawer设置,这是很糟糕的,因为你还要关闭这个drawer。一个可替代的方案(仅说明你能做什么,不是说这是最好的解决方案)是可以创建一个扩展的方法来做这些事情。
首先,我们创建一个consume
方法,意思是处理了这个event(返回true),接收一个lambda做我们分支要做的工作。对于drawer也一样可以这么做。
override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) {
R.id.action_settings -> consume { navigateToSettings() }
R.id.nav_camera -> drawer.consume { navigateToCamera() }
R.id.nav_gallery -> drawer.consume { loadGallery() }
R.id.nav_slideshow -> drawer.consume { loadSlideshow() }
else -> super.onOptionsItemSelected(item)
}
这些方法看起来是如何的?
inline fun consume(f: () -> Unit): Boolean {
f()
return true
}
对于drawer也类似:
inline fun DrawerLayout.consume(f: () -> Unit): Boolean {
f()
closeDrawers()
return true
}
好消息是这些函数是内联的
,意思是编译时这个方法会被方法的代码替代,所以在调用的地方编写代码是高效的。
这个代码显示了来自design support library的snack比toasts更不好用。但在Kotlin中我们可以做的更好。可以像下边这样写:
view.snack("This is my snack")
view.snack("This snack is short", Snackbar.LENGTH_SHORT)
如果我们有一个action怎么办?别急,Kotlin这样解决:
view.snack("Snack message") {
action("Action") { toast("Action clicked") }
}
我们可以为了被困扰任何事情创建小的DSLs。我们需要什么?
inline fun View.snack(message: String, length: Int = Snackbar.LENGTH_LONG, f: Snackbar.() -> Unit) {
val snack = Snackbar.make(this, message, length)
snack.f()
snack.show()
}
第一个方法是创建snackbar,让这个snackbar之行我们提供的扩展方法,并显示自己。
这个方法会创建Snackbar action。这个action方法看起来是这样的:
fun Snackbar.action(action: String, color: Int? = null, listener: (View) -> Unit) {
setAction(action, listener)
color?.let { setActionTextColor(color) }
}
你甚至可以指定这个action的文字的颜色。如果你没有设置,默认值是null,最后一行代码决定如何做。你不喜欢最后一行代码?
color?.let { setActionTextColor(color) }
let
内的代码只有color
不为空的时候才会被执行。
在Java中,例如当我们查找一个view时,我们必须等到activity的布局文件加载完毕才能赋值给一个变量。
同样的也发生在context身上。如果一个object依赖context,你需要在class开始的地方声明它,然后在onCreate
时候赋值。
用Kotlin委托,你仅需要委托一个值给lazy
委托,当第一次被使用的时候才会执行:
override val toolbar by lazy { find<Toolbar>(R.id.toolbar) }
override val dataBase by lazy { DataBase(this) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detail)
setSupportActionBar(toolbar)
dataBase.loadWhatever()
}
find
方法属于Anko库。但你可以更容易的做类似的事情:
inline fun <reified T : View> Activity.find(id: Int): T = findViewById(id) as T
在Java中所有的事情都要创建对象。一个例子就是在创建一个完整的Runnable
时的postDelayed
。Kotlin的interoperability仅需要创建一个lambda,它的可读性好很多:
view.postDelayed({ doWhatever() }, 200)
如果你想创建一个线程并运行一些东西该怎么做呢?
Thread().run {
// Running in a thread
}
感谢Anko库,我们有一个小的DSL来处理后台线程任务。
async() {
// Do something in a secondary thread
uiThread {
// Back to the main thread
}
}
它也是上下文感知的,所以如果它在antivity中被调用,如果activity关闭了,uiThread
也就不会被调用了。
简单的回答就是缺少lambdas和功能操作。但Kotlin可以利用它们来工作,所以排序、转换、映射和过滤只是一个函数的调用。
return parsedContacts.filter { it.name != null && it.image != null }
.sortedBy { it.name }
.map { Contact(it.id, it.name!!, it.image!!) }
对于集合,你可以查看complete list of operations。
谁说你不能像访问一个数组一样的访问ViewGroup
中的view?这是不是很好?但一定很困难...当然不。你只需要用acts as an operator.创建一个扩展方法。
operator fun ViewGroup.get(pos: Int): View = getChildAt(pos)
现在你可以这样做:
val view = viewGroup[2]
你甚至可以创建一个返回view列表的扩展属性:
val ViewGroup.views: List<View>
get() = (0 until childCount).map { getChildAt(it) }
现在你可以直接访问view:
val views = viewGroup.views
Kotlin中的数据类给你提供了这些所有。
data class Person(val name: String, val surname: String, val age: Int)
我们在这里做。
Anko也提供了一些好的方法可以不用创建intent、添加extras、调用方法...来启动另一个activity,所有的事情都可以用单独的一行代码做到:
startActivity<DetailActivity>("id" to 2, "name" to "Kotlin")
这回创建一个带有extras的intent,extras的值是该方法接收的一对列表参数值定义的。
使用Kotlin的Android扩展,仅需要添加一个专门的import,插件将会给activity、fragment甚至一个view创建一组参数设置,因此你不必担心去申明或找到这些view。参数的名称将在导入的XML文件中定义。例如,在RecyclerView
adapter里,ViewHolder
里你可以这么做:
import kotlinx.android.synthetic.main.item_contact.view.*
...
fun bindContact(contact: Contact) {
itemView.name.text = contact.name
itemView.avatar.loadUrl(contact.image)
itemView.setOnClickListener { listener(contact) }
}
也可以更简洁。如果你多次使用同一个变量,你可以用标准库中的一些方法,例如apply
:
fun bindContact(contact: Contact) = itemView.apply {
name.text = contact.name
avatar.loadUrl(contact.image)
setOnClickListener { listener(contact) }
}
偷偷的看下Kotlin能为你做什么。很多事情仅是一个提高速度、帮助编写更清晰的代码,避免模版的语法糖果,最重要的是,让你感觉好像一个忍者。
Kotlin有许多你想学习的更惊叹的特性。这个语言真的是很有乐趣并富有创造力的,它注重实效(仅是一组不可思议的功能)并且完全集成了Android开发。
我推荐你去看一本书,现在就获得他吧。
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。
今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。
特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。
据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。