有段时间没有写贴子,不管再怎么学好记性不如烂笔头,有空还是将脑袋里的东西记录一下的好,省的过个几个月不用又忘了。
anko作为kotlin开发android来说加入了很多简洁的语法,最注目的就是直接在代码里面写控件布局,而且看起来还很简洁像极了ios,android终于成熟起来了,越来越像ios开发了,anko做为kotlin的开发的框架将kotlin的简洁的语法发挥的淋漓尽致。
如果你写代码很忙,没时间去读一本Kotlin书的话了解kotlin语法,那么不妨去的看一下anko源码,一天也就通晓了kotlin的所有用法。
下面来看一下简单的登录用anko怎么写
verticalLayout(){
padding = dip(30)
editText {
hint = "Name"
textSize = 24f
onClick { }
}
editText {
hint = "Password"
textSize = 24f
}.lparams(0, wrapContent){
}
button("Login") {
textSize = 26f
}
}
看这代码多么的简洁,最外层用了垂直的线性布局,紧跟着两个输入框,然后一个登陆的按钮就直接完成了登陆的界面,而且不用调用setContentView布局就会加载显示,这比java写android要简洁太多了,写这个布局用java你得new四次控件,不断的set设置属性,不断add添加view,表示一年多的kotlin,再也不想用java了。
就算kotlin语法上要简洁,但也不可能像上面写法那么简洁,所有anko做了很多封装
inline fun Activity.verticalLayout(theme: Int = 0, init: (@AnkoViewDslMarker _LinearLayout).() -> Unit): LinearLayout {
return ankoView(`$$Anko$Factories$CustomViews`.VERTICAL_LAYOUT_FACTORY, theme, init)
}
这个垂直线性布局,anko是用了扩展函数实现的,然后它还是内联的,编译器会在编译的时候会将方法去掉。
可以看出此方法两个参数一个是主题一个是闭包函数,闭包函数在我看来就是和c的函数指针差不多,传的就是函数实现的指针
随后调用ankoView方法
inline fun <T : View> Activity.ankoView(factory: (ctx: Context) -> T, theme: Int, init: T.() -> Unit): T {
val ctx = AnkoInternals.wrapContextIfNeeded(this, theme)
val view = factory(ctx)
view.init()
AnkoInternals.addView(this, view)
return view
}
这两个方法的前缀都是加了Activity.,所以这两个方法都属于Activity的扩展方法,所以可以直接在activity方法里面直接调用,ankoView方法第一个参数也是一个方法闭包,返回的是View类型的,第三个参数又是一个闭包是调用了当前T的方法的闭包,那么传入的参数$$Anko$Factories$CustomViews`.VERTICAL_LAYOUT_FACTORY是一个返回View的方法
val VERTICAL_LAYOUT_FACTORY = { ctx: Context ->
val view = _LinearLayout(ctx)
view.orientation = LinearLayout.VERTICAL
view
}
可以看出传入的闭包函数最终创建了垂直的线性布局_LinearLayout
open class _LinearLayout(ctx: Context): LinearLayout(ctx)
接着看AnkoInternals.wrapContextIfNeeded函数
fun wrapContextIfNeeded(ctx: Context, theme: Int): Context {
return if (theme != 0 && (ctx !is AnkoContextThemeWrapper || ctx.theme != theme)) {
// If the context isn't a ContextThemeWrapper, or it is but does not have
// the same theme as we need, wrap it in a new wrapper
AnkoContextThemeWrapper(ctx, theme)
} else {
ctx
}
}
这里就是创建了新的Context,然后继续看val view = factory(ctx)这个代码就是调用了VERTICAL_LAYOUT_FACTORY这个方法,factory可以看做VERTICAL_LAYOUT_FACTORY方法的方法指针。
那么创建完View之后就调用了view.init()方法,这个方法其实就是
verticalLayout(){
}
verticalLayout闭包里的代码,最后调用 AnkoInternals.addView(this, view)将布局绑定到到Activity上,这里的this就是activity对象
override fun addView(view: View?, params: ViewGroup.LayoutParams?) {
if (view == null) return
if (myView != null) {
alreadyHasView()
}
this.myView = view
if (setContentView) {
doAddView(ctx, view)
}
}
private fun doAddView(context: Context, view: View) {
when (context) {
is Activity -> context.setContentView(view)
is ContextWrapper -> doAddView(context.baseContext, view)
else -> throw IllegalStateException("Context is not an Activity, can't set content view")
}
}
最终自己调用setContentView将布局和Activity绑定然后显示出来,不用我们自己写了
其实看完这些anko写布局为什么这么简洁就是用了Kotlin的扩展函数写法,将繁琐的布局控件声明,添加都帮我们实现了,所以才会用起来这么简单。