写点什么

Kotlin 修炼指南(三),如何在 Android-Studio 下进行 NDK 开发

用户头像
Android架构
关注
发布于: 8 小时前

简化下实际上就是下面的代码。


object Singleton {


fun xxx() {}}


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


反编译后看生成代码,这就是一个典型的饿汉式单例,借助静态代码块初始化的锁,初始化单例实例,从而实现单例效果。


public final class Singleton {public static final Singleton INSTANCE;


public final void xxx() {}


private Singleton() {}


static {Singleton var0 = new Singleton();INSTANCE = var0;}}

通过 object 代替匿名内部类

这是 object 的另一个比较常用的地方,也符合了 object 的语义,定义一个类,并生成该类的实例,也就是需要创建的匿名内部类。


viewPager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {override fun onPageScrollStateChanged(state: Int) {}


override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {}


override fun onPageSelected(position: Int) {}});

companion object

由于 Kotlin 中没有静态函数,所以在 Kotlin 中,可以使用 companion object 替代 Java 中的 static 修饰。


编译器会自动生成了一个叫做 Companion 的静态内部类。


在 Java 中调用伴生对象,可以使用 User.Companion.isMale(1)


class User {


companion object {const val DEFAULT_USER_AGE = 30}


fun test(){}}


// later, accessed like you would a static variable:user.age = User.DEFAULT_USER_AGE

Kotlin 函数

在 Kotlin 的基础库中,系统提供了大量针对函数的优化,解决了很多在 Java 代码中写起来不太爽的地方。

显式参数

在 Java 中,当一个函数的参数值太多时,需要一个个对齐参数,虽然可以通过 IDE 的快捷提示等功能来展示,但始终用起来不太方便,而在 Kotlin 中,除了像 Java 中那样按顺序的传递参数外,还可以通过指定参数名的方式进行参数传递。


fun test(name: String, age: Int) {}


test(name = "xys", age = 18)


参数含义一目了然,提高了代码的可读性。

参数默认值

fun test(name: String = "xys", age: Int) {}


fun a() {test(age = 18)}


通过参数默认值,可以避免 Java 下大量参数下的重载函数,当某个参数可以使用默认值时,就不用显示的声明了,类似 Java 中的不同参数的重载函数。


在 Java、Kotlin 混编的时候,无法避免的会混合调用,可以通过 @JvmOverloads 注解,给 Java 代码生成重载的函数。

拓展函数

拓展函数可以说是 Kotlin 最为重要的黑魔法之一了,通过拓展函数,可以给一些系统类添加原本没有的函数,极大的提高了函数的可拓展性。


fun Activity.toast(msg: String) {Toast.makeText(this, msg, Toast.LENGTH_SHORT).show()}

拓展属性

与拓展函数类似,拓展属性可以给现有属性拓展自定义的实现。


val String.lastChar: Charget() = get(length - 1)


拓展功能看上去比较神奇,但大家可以通过查看 Kotlin 生成的 class 代码,反编译成的 Java 代码来看它具体的实现方法。


对于扩展函数来说,转化为 Java 代码的时候,其实就是生成一个静态的函数,这个静态函数的第一个参数就是该类的实例对象,所以这样把类的实例传入函数以后,函数内部就可以访问到类的公有方法。


扩展属性也是类似,获取的扩展属性会生成为一个静态的 get 函数,同时这个静态函数的第一个参数就是该类的实例对象,设置的扩展属性会转化为一个静态的 set 函数,同时这个静态函数的第一个参数就是该类的实例对象。函数内部可以访问公有的方法和属性。


在了解了其实现原理后,可以发现,拓展函数一定是 static 的,且不能被 override,也不存在运行时类型,其类型在编译时就已经确定,同时扩展函数和扩展属性内只能访问到类的公有方法和属性,私有的和 protected 同样是不能访问的。


拓展函数和拓展属性只是 Kotlin 语法的障眼法,并没有实际的去修改一个类

嵌套函数

函数是 Kotlin 中的第一公民,所以函数可以出现在 Kotlin 中的任何一个地方,包括在一个函数中。


在一个函数中定义另一个函数,可以很好的将这个函数的使用限制在当前的外层函数中,避免对外暴露不必要的接口,同时还能避免重复的模板代码,例如下面这个例子。


class User(val id: Int, val name: String, val address: String, val email: String)


fun check(user: User) {if (user.name.isEmpty()) {throw IllegalArgumentException("Can't save user {user.id}: empty Name")}if (user.address.isEmpty()) {throw IllegalArgumentException("Can't save user {user.id}: empty Address")}if (user.email.isEmpty()) {throw IllegalArgumentException("Can't save user ${user.id}: empty Email")}// ...}


通过嵌套函数实现。


fun saveUser2(user: User) {fun validate(value: String, fildName: String) {if (value.isEmpty()) {throw IllegalArgumentException("Can't save user fildName")}}


validate(user.name, "Name")validate(user.address, "Address")validate(user.email, "Email")// ...}

工具类函数

由于在 Kotlin 中,函数可以脱离类而独立存在,所以这对于工具类函数来说,就非常方便了,不用再定义一个 ToolUtil 类,而可以直接写在文件中。

作用域函数

作用域函数在[Kotlin 修炼指南(一)](


)中已经有详细介绍了。

设计模式

设计模式最早是在面向对象编程的基础上提出来的编程范式,但是对于函数式编程来说,有很多定义都过于教条了,所以,现代式的编程语言,通过很多语法上的定义,就已经实现了很多种设计模式。

单例模式

前面已经提到了,通过 object class,就可以很轻松的实现一个线程安全的单例类。

静态工厂模式

借助运算符重载,可以很方便的实现静态工厂模式。


interface Car {val brand: String


companion object {operator fun invoke(type: CarType): Car {return when (type) {CarType.AUDI -> Audi()


CarType.BMW -> BMW()}}}}


通过重载了 invoke()函数,在调用 Car(CarType.BMW)的时候,就创建好了对应的工厂实例。

代理模式 策略模式

代理模式,或者说策略模式,都可以通过 Kotlin 中的类委托来实现。


interface BaseTTS {fun doTTS()}


class BaiDuTTS : BaseTTS {override fun doTTS() {print("BaiDu")}}


class TencentTTS : BaseTTS {override fun doTTS() {print("Tencent")}}


class TTSCategory(tts: BaseTTS) : BaseTTS by tts


fun doTest() {TTSCategory(BaiDuTTS()).doTTS()}


通过类委托,将 tts 的实现代理出来。


更进一步,可以通过匿名类的方式,直接创建代理类的实现。


interface BaseTTS {fun doTTS()}


class TTSCategory(tts: BaseTTS) : BaseTTS by tts {override fun doTTS() {print("Do tts")}}


而当策略中只有一个函数的时候,还可以进一步简化,把策略直接封装成 Lambda 表达式。


class TTSCategory(val strategy: () -> Unit) {fun doTTS() {strategy.invoke()}}


fun test() {TTSCategory { print("Do tts") }.doTTS()}

装饰器模式

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
Kotlin修炼指南(三),如何在Android-Studio下进行NDK开发