初学Kotlin——在自定义View里的应用

fun shadow(width:Int=100,height:Int = 180){ }
//你可以这么使用
shadow()
shadow(140)
shadow(140,200)

4.UI布局

一般用我们创造view的布局是xml,Kotlin也是支持的,但是它更推荐你使用Anko的布局方式。

那是什么是Anko呢,AnkoJetBrains开发的一个强大的库,它主要的目的是用来替代以前xml的方式来使用代码生成UI布局的,它包含了很多的非常有帮助的函数和属性来避免让你写很多的模版代码。

有兴趣的你可以去看看它的源码与更多使用方式 – Anko

首先你要在Gradle里添加Anko的引用

// Anko Layouts
compile “org.jetbrains.anko:anko-recyclerview-v7: a n k o v e r s i o n " c o m p i l e " o r g . j e t b r a i n s . a n k o : a n k o − r e c y c l e r v i e w − v 7 − c o r o u t i n e s : anko_version" compile "org.jetbrains.anko:anko-recyclerview-v7-coroutines: ankoversion"compile"org.jetbrains.anko:ankorecyclerviewv7coroutines:anko_version”
compile “org.jetbrains.anko:anko-sdk25: a n k o v e r s i o n " c o m p i l e " o r g . j e t b r a i n s . a n k o : a n k o − a p p c o m p a t − v 7 : anko_version" compile "org.jetbrains.anko:anko-appcompat-v7: ankoversion"compile"org.jetbrains.anko:ankoappcompatv7:anko_version”
// Coroutine listeners for Anko Layouts
compile “org.jetbrains.anko:anko-sdk25-coroutines: a n k o v e r s i o n " c o m p i l e " o r g . j e t b r a i n s . a n k o : a n k o − a p p c o m p a t − v 7 − c o r o u t i n e s : anko_version" compile "org.jetbrains.anko:anko-appcompat-v7-coroutines: ankoversion"compile"org.jetbrains.anko:ankoappcompatv7coroutines:anko_version”

然后你可以在代码里写UI布局的代码了,就是用Kotlin代码替代xml

private fun createView(attrs: AttributeSet? = null, defStyleAttr: Int = 0) {

var height = dip(150)
attrs?.let {
val typeArray = mContext.obtainStyledAttributes(it, R.styleable.BarChartView, defStyleAttr, 0)
height = typeArray.getDimension(R.styleable.BarChartView_chart_height, dip(150).toFloat()).toInt()
typeArray.recycle()
}

verticalLayout {
lparams(width = matchParent, height = matchParent)

frameLayout {
lparams(width = matchParent, height = wrapContent)

mLineView = view {
backgroundColor = R.color.gray_light
}.lparams(width = matchParent, height = dip(0.5f)) {
gravity = Gravity.BOTTOM
bottomMargin = dip(9)
}

mBarView = recyclerView {
lparams(width = matchParent, height = height)
}
}

mDateView = relativeLayout {
lparams(width = matchParent, height = wrapContent) {
leftPadding = dip(10)
rightPadding = dip(10)
}

mLeftTv = textView {
textSize = 15f
}

mRightTv = textView {
textSize = 15f
}.lparams(width = wrapContent, height = wrapContent) {
alignParentRight()
}
}
}
}

可以从代码里看见verticalLayout(其实就是LinearLayoutvertical模式)包裹了frameLayoutrelativeLayout,里面又有各自的子view,而且你会发现xml有的属性这里也有,调用起来非常的简洁明了,熟练xml的来写这个,我觉得上手应该会很快,它的缺点就是没有预览效果,以及实现复杂的view结构的时候会比较繁琐,考验盲写的功力了。。。。

5.扩展函数

扩展函数是Kotlin非常方便实用的一个功能,它可以让我们随意的扩展SDK的库,你如果觉得SDK的api不够用,这个时候你可以用扩展函数完全去自定义。

例如你需要这样来获取颜色,每次你都需要一个上下文context

mColor = ContextCompat.getColor(mContext, R.color.primary)

那你可以通过扩展Context这个SDK的类来实现更方便的使用

fun Context.color(colorRes: Int) = ContextCompat.getColor(this, colorRes)
fun View.color(colorRes: Int) = context.color(colorRes)

而且为了更方便在View里面使用,又扩展了View。在第一个方法里面可以发现getColor所需要的this上下文,就是Context。同样,View里面的contextgetContext()所得到,也就是View里面本身具有的公有方法。

这其实是很惊艳的功能

那我们可以想一想为啥可以这样做,我们知道的是KotlinJava都是在Jvm上运行的,既然都是编译成class字节码,那我们是不是可以通过字节码来了解一些事情。

通过Android studio 3.0上的Tools的工具Show Kotlin Bytecode,可以将刚才的扩展函数的代码编译成字节码

// access flags 0x19
public final static color(Landroid/content/Context;I)I
@Lorg/jetbrains/annotations/NotNull;() // invisible, parameter 0
L0
ALOAD 0
LDC “$receiver”
INVOKESTATIC kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull (Ljava/lang/Object;Ljava/lang/String;)V
L1
LINENUMBER 12 L1
ALOAD 0
ILOAD 1
INVOKESTATIC android/support/v4/content/ContextCompat.getColor (Landroid/content/Context;I)I
IRETURN
L2
LOCALVARIABLE $receiver Landroid/content/Context; L0 L2 0
LOCALVARIABLE colorRes I L0 L2 1
MAXSTACK = 2
MAXLOCALS = 2

// access flags 0x19
public final static color(Landroid/view/View;I)I
@Lorg/jetbrains/annotations/NotNull;() // invisible, parameter 0
L0
ALOAD 0
LDC “$receiver”
INVOKESTATIC kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull (Ljava/lang/Object;Ljava/lang/String;)V
L1
LINENUMBER 14 L1
ALOAD 0
INVOKEVIRTUAL android/view/View.getContext ()Landroid/content/Context;
DUP
LDC “context”
INVOKESTATIC kotlin/jvm/internal/Intrinsics.checkExpressionValueIsNotNull (Ljava/lang/Object;Ljava/lang/String;)V
ILOAD 1
INVOKESTATIC shadow/barchart/ExtensionsKt.color (Landroid/content/Context;I)I
IRETURN
L2
LOCALVARIABLE $receiver Landroid/view/View; L0 L2 0
LOCALVARIABLE colorRes I L0 L2 1
MAXSTACK = 3
MAXLOCALS = 2

这就是编译后的字节码,看不懂是吧,我也看不懂。。但是我们可以反编译啊,生成Java代码

public static final int color(@NotNull Context KaTeX parse error: Expected '}', got 'EOF' at end of input: …meterIsNotNull(receiver, " r e c e i v e r " ) ; r e t u r n C o n t e x t C o m p a t . g e t C o l o r ( receiver"); return ContextCompat.getColor( receiver");returnContextCompat.getColor(receiver, colorRes);
}

public static final int color(@NotNull View KaTeX parse error: Expected '}', got 'EOF' at end of input: …meterIsNotNull(receiver, “$receiver”);
Context var10000 = $receiver.getContext();
Intrinsics.checkExpressionValueIsNotNull(var10000, “context”);
return color(var10000, colorRes);
}

通过反编译我们可以知道这是个静态函数,Intrinsics.checkParameterIsNotNull($receiver, "$receiver");这个函数只起到了判空的作用,真正的代码是return ContextCompat.getColor($receiver, colorRes);这个不就是我们刚刚用的Java代码嘛。

重点是$receiver接收的对象,接收的是Context实例,这样的话就可以调用这个类的所有公有方法和公有属性,而且它是静态函数,它可以通过类直接调用。所以扩展函数的实现只不过是加了一个需要当前对象的静态方法,调用的时候传入一个当前对象而已。

我们刚刚用到了反编译,因为我们知道KotlinJava的生成字节码是一样的,那我们可以了解一下Kotlin的编译过程,它跟Java的区别是什么。可以看一下这篇文章Kotlin编译过程分析

通过这篇文章你可以了解到Kotlin在编译过程中,与Java是大致相同的,只是在最后生成目标代码的时候做了很多类似于封装的事情,生成相同的语法结构,Kotlin将我们本来在代码层做的一些封装工作转移到了编译后端阶段。那我们可不可以在学习Kotlin的时候去这样理解,其实Kotlin是一种封装了Java的强大的语法糖,Java做不到的事情,Kotlin其实也做不到,例如对象只能访问公有属性。

6.数据类

Kotlin中你要实现数据类是非常简单的,并不需要手动加上get/set方法

data class BarItem(
private val barData: BarData,
var select: Boolean = false) {
fun getData(): Double {
return barData.getData()
}

fun getTag(): String {
return barData.getTag()
}
}

在这个类里面你会发现,我还声明了两个方法,我需要的是BarData里的数据,但又不仅仅只需要这个数据,所以我声明了一个类来封装它,其实这个相当于装饰者模式了。Kotlin有更好的方式实现这个模式

data class BarItem(
private val barData: BarData,
var select: Boolean = false) : BarData by barData

7.when

BarChartView里用到一个与switch语法类似的语句

mSelectPosition = when (mStyle) {
ScrollStyle.DEFAULT -> mDataList.size - 1
ScrollStyle.START -> 0
ScrollStyle.NONE -> -1
ScrollStyle.CUSTOM -> mSelectPosition
else -> { }
}

它是起到了跟switch一样的作用,并且更强大,因为它是表达式,所以是有返回值的,在Kotlin中控制流大都是表达式,都是可以有返回值的。

8.集合

Kotlin是区分可变集合和不可变集合的,它给你提供这两种选择。

//不可变
Set
Map<K, out V>
List
//可变
MutableSet
MutableMap<K, V>
MutableList

不可变的集合提供只读属性,例如size,get等,Kotlin不提供专门的语法结构创建list或者set,是用标准库获取的,我们可以看一下它的源码是怎样实现。

/**

  • Returns an immutable list containing only the specified object [element].
  • The returned list is serializable.
  • @sample samples.collections.Collections.Lists.singletonReadOnlyList
    /
    @JvmVersion
    public fun listOf(element: T): List = java.util.Collections.singletonList(element)
    /
    *
  • Returns an empty new [MutableList].
  • @sample samples.collections.Collections.Lists.emptyMutableList
    */
    @SinceKotlin(“1.1”)
    @kotlin.internal.InlineOnly
    public inline fun mutableListOf(): MutableList = ArrayList()
    从源码可以看见这是Javajava.util.Collections.singletonListArrayList,这就可以理解为啥不可变和可变的了。。。

总结

Kotlin相对于Java,更像是封装了Java的强大语法糖,使用了更简洁的语法提高了生产力。

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助

因此我收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门**

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值