您的位置 首页 java

使用Kotlin高效地开发Android App(一)

一.apply 函数 和 run 函数

1.1 apply函数

apply函数是指在函数块内可以通过 this 指代该对象,返回值为该对象自己。在链式调用中,可以考虑使用它来不破坏链式。

/**
 * Calls the specified function [block] with `this` value as its receiver and returns `this` value.
 */
@ kotlin . internal .InlineOnly
public inline fun <T> T.apply(block: T.() -> Unit): T {
 contract {
 callsInPlace(block, InvocationKind.EXACTLY_ONCE)
 }
 block()
 return this
}
 

举个例子:

/**
 * Created by tony on 2018/4/26.
 */
object Test {
 @JvmStatic
 fun main(args: Array<String>) {
 val result ="Hello".apply {
 println(this+" World")
 this+" World"
 }
 println(result)
 }
}
 

执行结果:

Hello World
Hello
 

第一个 字符串 是在 闭包 中打印的,第二个字符串是result的结果,它仍然是“Hello”。

1.2 run函数

run函数类似于apply函数,但是run函数返回的是最后一行的值。

/**
 * Calls the specified function [block] with `this` value as its receiver and returns its result.
 */
@kotlin.internal.InlineOnly
public inline fun <T, R> T.run(block: T.() -> R): R {
 contract {
 callsInPlace(block, InvocationKind.EXACTLY_ONCE)
 }
 return block()
}
 

举个例子:

/**
 * Created by tony on 2018/4/26.
 */
object Test {
 @JvmStatic
 fun main(args: Array<String>) {
 val result ="Hello".run {
 println(this+" World")
 this + " World"
 }
 println(result)
 }
}
 

执行结果:

Hello World
Hello World
 

第一个字符串是在闭包中打印的,第二个字符串是result的结果,它返回的是闭包中最后一行的值,所以也打印“Hello World”。

1.3 项目中的使用

在App的反馈页面中,需要输入邮箱、主题、内容才能完成反馈按钮的提交。

最初的写法是这样:

 if (viewModel.email.value!!. isEmpty ()) {
 toast(resources.getString(R.string.you_have_not_completed_the_email_address)).show()
 return@onClickRight
 }
 if (!Util.checkEmail(viewModel.email.value!!)) {
 toast(resources.getString(R.string.the_email_format_you_have_filled_is_incorrect)).show()
 return@onClickRight
 }
 if (viewModel.subject.value!!.isEmpty()) {
 toast(resources.getString(R.string.you_have_not_completed_the_feedback_subject)).show()
 return@onClickRight
 }
 if (viewModel.content.value!!.isEmpty()) {
 toast(resources.getString(R.string.you_have_not_completed_the_details)).show()
 return@onClickRight
 }
 

修改成只使用apply函数

 viewModel.apply {
 if (email.value!!.isEmpty()) {
 toast(resources.getString(R.string.you_have_not_completed_the_email_address)).show()
 return@onClickRight
 }
 if (!Util.checkEmail(email.value!!)) {
 toast(resources.getString(R.string.the_email_format_you_have_filled_is_incorrect)).show()
 return@onClickRight
 }
 if (subject.value!!.isEmpty()) {
 toast(resources.getString(R.string.you_have_not_completed_the_feedback_subject)).show()
 return@onClickRight
 }
 if (content.value!!.isEmpty()) {
 toast(resources.getString(R.string.you_have_not_completed_the_details)).show()
 return@onClickRight
 }
 }
 

感觉不够cool,可以结合run和apply函数一起使用

 viewModel.email.run {
 if (value!!.isEmpty()) {
 toast(resources.getString(R.string.you_have_not_completed_the_email_address)).show()
 return@onClickRight
 }
 if (!Util.checkEmail(value!!)) {
 toast(resources.getString(R.string.the_email_format_you_have_filled_is_incorrect)).show()
 return@onClickRight
 }
 viewModel
 }.subject.run {
 if (value!!.isEmpty()) {
 toast(resources.getString(R.string.you_have_not_completed_the_feedback_subject)).show()
 return@onClickRight
 }
 viewModel
 }.content.apply {
 if (value!!.isEmpty()) {
 toast(resources.getString(R.string.you_have_not_completed_the_details)).show()
 return@onClickRight
 }
 }
 

二.data class

Kotlin的data class有点类似于Scala的case class。

以下的Java Bean代码

/**
 * Created by tony on 2018/4/27.
 */
public class User {
 public String userName;
 public String password;
}
 

等价于

data class User (var userName: String? = null,var password: String? = null)
 

可以看到采用data class能够简化 Java Bean类。我们的App采用了MVVM的架构,因此对应Model类全部使用data class。

三.无需使用findViewById 或者 butterknife

使用Kotlin Android Extensions插件即可实现该功能,它是Kotlin 插件的组成之一,无需再单独安装插件。

我们在各个modules的build.gradle中添加该插件,即可使用。

apply plugin: 'kotlin-android-extensions'
 

布局文件中的id,可以直接在代码中使用。

首先,按照import kotlinx.android.synthetic.main.布局文件名*的方式导入。

例如MainActivity,它的布局文件是activity_main.xml

则按照如下的方式进行import

import kotlinx.android.synthetic.main.activity_main.*
 

那么activity_main.xml中控件的id,可以直接在MainActivity中使用,无需使用findViewById 或者 butterknife。是不是特别方便?

四.点击事件的 埋点 处理

App的埋点,使用自己家的产品–魔窗的sdk来做事件的埋点。

如果使用Java来开发App,可以使用AOP来实现埋点。由于我们的App采用Kotlin编写,Kotlin可以将事件的点击简化成如下的形式

 view.setOnClickListener {
 ....
 }
 

这种简化了的lambda表达式,所以我还是老老实实的使用传统方式进行埋点。

使用Kotlin的通常做法:

 view.setOnClickListener {
 TrackAgent.currentEvent().customEvent(eventName)
 ....
 }
 

或者

 view.setOnClickListener {
 TrackAgent.currentEvent().customEvent(eventName, trackMap)
 ....
 }
 

后来,我写了一个View的扩展函数click,后来经过同事的优化

目前,已经将该扩展函数放入我的Kolin的工具类库

此时,埋点的代码变成这样

 view.click {
 TrackAgent.currentEvent().customEvent(eventName)
 ....
 }
 

或者

 view.click {
 TrackAgent.currentEvent().customEvent(eventName, trackMap)
 ....
 }
 

进一步的优化处理,对于View增加扩展函数clickWithTrack专门用于埋点的点击事件。

package cn.magicwindow.core.ext
import android.view.View
import cn.magicwindow.TrackAgent
import com.safframework.ext.clickWithTrigger
/**
 *
 * @FileName:
 * cn.magicwindow.core.ext.ViewExt.java
 * @author: Tony Shen
 * @date: 2018-04-24 17:17
 * @version V1.0 <描述当前版本功能>
 */
fun <T : View> T.clickWithTrack(eventName: String, time:  Long  = 600, block: (T) -> Unit) = this.clickWithTrigger(time) {
 TrackAgent.currentEvent().customEvent(eventName)
 block(it as T)
}
fun <T : View> T.clickWithTrack(eventName: String, trackMap: HashMap<String, String>, time: Long = 600, block: (T) -> Unit) = this.clickWithTrigger(time) {
 TrackAgent.currentEvent().customEvent(eventName, trackMap)
 block(it as T)
}
 

此时埋点可以这样使用:

 view.clickWithTrack(key) {
 ....
 }
 

或者

 view.clickWithTrack(key,trackMap) {
 ....
 }
 

创作不易喜欢的话记得点击+关注哦

文章来源:智云一二三科技

文章标题:使用Kotlin高效地开发Android App(一)

文章地址:https://www.zhihuclub.com/181971.shtml

关于作者: 智云科技

热门文章

网站地图