Kotlin函数参数默认值
合并前:
fun toast(string: String) {
toast(string, Toast.LENGTH_SHORT)
}
fun toast(string: String, duration: Int) {
Toast.makeText(BaseApplication.currentApplication, string, duration).show()
}
合并后:
@JvmOverloads
fun toast(string: String, duration: Int = Toast.LENGTH_SHORT) {
Toast.makeText(BaseApplication.currentApplication, string, duration).show()
}
在Kotlin中调用,传一个参数或者两个参数,都可以调用
但是,如果在java代码中只能调用2个参数的方法,调用一个参数的方法报错,所以要加一个注解 @JvmOverloads
Kotlin扩展函数
原函数:
fun dp2px(dp: Float): Float {
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, displayMetrics)
}
改为扩展函数:
//扩展函数,相当于在不改变源码的情况下,给Float添加一个新函数dp2px
//调用:6f.dp2px()
fun Float.dp2px(): Float {
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, this, displayMetrics)
}
内联函数:inline
fun main() {
//编译的时候,就是相当于把代码复制过来,可以通过代码转换看出来
//Log.e("zhoujian","Android开发")
//Log.e("zhoujian","Kotlin学习")
logMessage()
}
//内联函数 inline
//作用:减少一层调用栈
//劣势:打包代码量变多
//内联函数 inline对于传入类型是函数参数就有意义的
inline fun logMessage() {
Log.e("zhoujian", "Android开发")
Log.e("zhoujian", "Kotlin学习")
}
Kotlin中函数参数类型
fun onClick(view: View) {
println("View点击了")
}
class View {
//(view:View)-> Unit 传入的就是一个函数类型
//函数类型是由函数接受参数、 -> 、函数返回类型三部分构成
fun setOnClickListener(listener: (view: View) -> Unit) {
}
}
fun main() {
var view: View = View()
//传入一个函数 两个冒号+函数名 就把函数传进来了
//view.setOnClickListener(::onClick)
//另外一种传递方式:Lambda表达式方式传递函数参数
view.setOnClickListener {
println("View点击了")
}
}
在java中调用 函数参数
//在java中调用函数参数
View view = new View();
view.setOnClickListener(new Function1<View, Unit>() {
@Override
public Unit invoke(View view) {
return null;
}
});
对于不是内联函数的函数,传入函数类型参数,会产生额外对象,浪费内存
如果使用内联函数,就不会产生额外的对象
Kotlin中的 by lazy
override val presenter by lazy {
// presenter第一次使用时创建,而且对象只会被创建一次
LessonPresenter(this)
}
Kotlin中的标准函数(或者叫作用域函数)
run with apply also let
主要区别是:返回参数不一样;作用域代码块中指代的调用者参数不一样(this 、 it)
标准函数的作用:可以将逻辑连贯代码放在一个作用域里面,让代码可读性更好
初始化Paint,并设置初始值,这是一个逻辑连贯的代码
改造前:
private val paint: Paint = Paint()
//:super(context,attrs) 调用父类构造函数
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
setTextSize(TypedValue.COMPLEX_UNIT_SP, 18f)
gravity = Gravity.CENTER
setBackgroundColor(getContext().getColor(R.color.colorPrimary))
setTextColor(Color.WHITE)
paint.isAntiAlias = true
paint.style = Paint.Style.STROKE
paint.color = getContext().getColor(R.color.colorAccent)
paint.strokeWidth = 6f.dp2px()
updateCode()
}
改造后:
private val paint: Paint = Paint().apply {
this.isAntiAlias = true
this.style = Paint.Style.STROKE
this.color = getContext().getColor(R.color.colorAccent)
this.strokeWidth = 6f.dp2px()
}
//:super(context,attrs) 调用父类构造函数
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
setTextSize(TypedValue.COMPLEX_UNIT_SP, 18f)
gravity = Gravity.CENTER
setBackgroundColor(getContext().getColor(R.color.colorPrimary))
setTextColor(Color.WHITE)
updateCode()
}
或者用 let
private val paint: Paint = Paint().let {
it.isAntiAlias = true
it.style = Paint.Style.STROKE
it.color = getContext().getColor(R.color.colorAccent)
it.strokeWidth = 6f.dp2px()
return@let it
}
改造前:
val state:Lesson.State? = lesson.state
if (state != null) {
setText(R.id.tv_state, state.stateName())
var colorRes = when (state) {
Lesson.State.PLAYBACK -> R.color.playback
Lesson.State.LIVE -> R.color.live
Lesson.State.WAIT -> R.color.wait
}
val backgroundColor = itemView.context.getColor(colorRes)
getView<View>(R.id.tv_state).setBackgroundColor(backgroundColor)
}
改造后:
lesson.state?.let {
setText(R.id.tv_state, it.stateName())
var colorRes = when (it) {
Lesson.State.PLAYBACK -> R.color.playback
Lesson.State.LIVE -> R.color.live
Lesson.State.WAIT -> R.color.wait
}
val backgroundColor = itemView.context.getColor(colorRes)
getView<View>(R.id.tv_state).setBackgroundColor(backgroundColor)
}
最后一个例子:
改造前:
refreshLayout = findViewById(R.id.swipe_refresh_layout)
refreshLayout!!.setOnRefreshListener { presenter.fetchData() }
refreshLayout!!.isRefreshing = true
改造后:
refreshLayout = findViewById(R.id.swipe_refresh_layout)
refreshLayout.apply {
setOnRefreshListener { presenter.fetchData() }
isRefreshing = true
}