使用Kotlin高效地开发Android App(五)完结篇

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/SLFq6OF5O7aH/article/details/80809700

640?wx_fmt=jpeg


一. 单例

使用 Java 来编写单例模式的话,可以写出好几种。同样,使用 Kotlin 也可以写出多种单例模式。在这里介绍的是一种使用委托属性的方式来实现单例的写法。

首先,Kotlin 在语法层面上支持委托模式。

委托模式是软件设计模式中的一项基本技巧。在委托模式中,有两个对象参与处理同一个请求,接受请求的对象将请求委托给另一个对象来处理。委托模式是一项基本技巧,许多其他的模式,如状态模式、策略模式、访问者模式本质上是在更特殊的场合采用了委托模式。委托模式使得我们可以用聚合来替代继承。

对于一些很常见的属性,虽然我们可以在每次需要它们的时候手动地实现它们,但更好的方法是一次性全部实现,然后放进一个库里面。换句话说,对其属性值的操作不再依赖于其自身的getter()/setter()方法,而是将其托付给一个代理类,从而每个使用类中的该属性可以通过代理类统一管理。这种方式是 委托属性

在Kotlin的标准库中有一系列的标准委托,not null属性是其中之一。它会含有一个可null的变量并会在我们设置这个属性的时候分配一个真实的值。如果这个值在被获取之前没有被分配,它就会抛出一个异常。

当然 by lazy 也可以实现单例,下面我们使用 not null 委托来实现 Application 的单例。

 
  
  1. class App : Application() {

  2.    companion object {

  3.        var instance: App by Delegates.notNull()

  4.    }

  5.    override fun onCreate() {

  6.            super.onCreate()

  7.            instance = this

  8.    }

  9. }

二. 封装Extras

使用ExtrasDelegate来封装Extras

 
  
  1. import android.support.v4.app.Fragment

  2. import android.support.v7.app.AppCompatActivity

  3. import kotlin.reflect.KProperty

  4. /**

  5. *

  6. * @FileName:

  7. *          com.safframework.delegate.extras.Extras.kt

  8. * @author: Tony Shen

  9. * @date: 2018-06-11 23:56

  10. * @version V1.0 <描述当前版本功能>

  11. */

  12. class ExtrasDelegate<out T>(private val extraName: String, private val defaultValue: T) {

  13.    private var extra: T? = null

  14.    operator fun getValue(thisRef: AppCompatActivity, property: KProperty<*>): T {

  15.        extra = getExtra(extra, extraName, thisRef)

  16.        return extra ?: defaultValue

  17.    }

  18.    operator fun getValue(thisRef: Fragment, property: KProperty<*>): T {

  19.        extra = getExtra(extra, extraName, thisRef)

  20.        return extra ?: defaultValue

  21.    }

  22. }

  23. fun <T> extraDelegate(extra: String, default: T) = ExtrasDelegate(extra, default)

  24. fun extraDelegate(extra: String) = extraDelegate(extra, null)

  25. @Suppress("UNCHECKED_CAST")

  26. private fun <T> getExtra(oldExtra: T?, extraName: String, thisRef: AppCompatActivity): T? =

  27.        oldExtra ?: thisRef.intent?.extras?.get(extraName) as T?

  28. @Suppress("UNCHECKED_CAST")

  29. private fun <T> getExtra(oldExtra: T?, extraName: String, thisRef: Fragment): T? =

  30.        oldExtra ?: thisRef.arguments?.get(extraName) as T?

封装完之后,在MainActivity中传递参数跳转到其他到Activity。

 
  
  1. import android.content.Intent

  2. import android.os.Bundle

  3. import android.support.v7.app.AppCompatActivity

  4. import com.safframework.delegate.R

  5. import com.safframework.delegate.domain.User

  6. import com.safframework.ext.click

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

  8. /**

  9. *

  10. * @FileName:

  11. *          com.safframework.delegate.activity.MainActivity.java

  12. * @author: Tony Shen

  13. * @date: 2018-06-13 12:03

  14. * @version V1.0 <描述当前版本功能>

  15. */

  16. class MainActivity:AppCompatActivity() {

  17.    public override fun onCreate(savedInstanceState: Bundle?) {

  18.        super.onCreate(savedInstanceState)

  19.        setContentView(R.layout.activity_main)

  20.        initViews()

  21.    }

  22.    private fun initViews() {

  23.        text1.click{

  24.            val intent = Intent(this@MainActivity, Demo4ExtrasDelegateActivity::class.java)

  25.            val u = User("Tony","123456")

  26.            intent.putExtra("user",u)

  27.            intent.putExtra("string","just a test")

  28.            startActivity(intent)

  29.        }

  30.        text2.click {

  31.            val intent = Intent(this@MainActivity, Demo4PrefsDelegateActivity::class.java)

  32.            startActivity(intent)

  33.        }

  34.    }

  35. }

这里的click函数,在使用Kotlin高效地开发Android App(二)中已经讲述过,就不在重复讲述。

Demo4ExtrasDelegateActivity接受从MainActivity中传递过来的参数。

 
  
  1. import android.os.Bundle

  2. import android.support.v7.app.AppCompatActivity

  3. import com.safframework.delegate.domain.User

  4. import com.safframework.delegate.extras.extraDelegate

  5. import com.safframework.log.L

  6. /**

  7. *

  8. * @FileName:

  9. *          com.safframework.delegate.activity.Demo4ExtrasDelegateActivity.java

  10. * @author: Tony Shen

  11. * @date: 2018-06-13 17:42

  12. * @version V1.0 <描述当前版本功能>

  13. */

  14. class Demo4ExtrasDelegateActivity: AppCompatActivity() {

  15.    private val user: User? by extraDelegate("user")

  16.    private val s:String? by extraDelegate("string")

  17.    public override fun onCreate(savedInstanceState: Bundle?) {

  18.        super.onCreate(savedInstanceState)

  19.        L.json(user)

  20.        L.i(s)

  21.    }

  22. }

所传递过来的任何对象类型,都可以使用如下的方式获取Extras。只要保证,extra的key正确即可。

 
  
  1.    private val user: User? by extraDelegate("user")

  2.    private val s:String? by extraDelegate("string")

与Extra类似,SharedPreferences也可以使用属性委托的方式进行封装。

三. infix

中缀表达式是一种通用的算术或逻辑公式表示方法,操作符以中缀形式处于操作数的中间。中缀表达式允许我们使用一个单词或字母来当运算符用(其本质还是函数调用),忽略调用的点和圆括号。

Kotlin的中缀表达式,需要满足以下条件:

  1. 使用infix修饰

  2. 只有一个参数

  3. 其参数不得接受可变数量的参数且不能有默认值。

例如:

 
  
  1. infix fun Int.add(i:Int):Int = this + i

  2. infix fun Int.加(i:Int):Int = this + i

  3. fun main(args: Array<String>) {

  4.    println(5 add 10)

  5.    println(5 10)

  6. }

执行结果:

 
  
  1. 15

  2. 15

在 Kotlin 中,使用中缀表达式最经典的例子,莫过于使用kxdate来操作日期。 kxdate github地址:https://github.com/yole/kxdate

 
  
  1. val twoMonthsLater = 2.months.fromNow

  2. val yesterday = 1.days.ago

等价于:

 
  
  1. val twoMonthsLater = 2 months fromNow

  2. val yesterday = 1 days ago

由此可见,中缀表达式能让代码看起来更加接近于自然语言。

四. inline

Kotlin 天生支持函数式编程,高阶函数和 lambda 是其一大特色。

使用高阶函数会带来一些运行时间效率的损失:每一个函数都是一个对象,并且都会捕获一个闭包。 即那些在函数体内会被访问的变量。 内存分配(对于函数对象和类)和虚拟调用会引入运行时间开销。

使用 inline 修饰的函数,可以从编译器角度将函数的函数体复制到调用处实现内联。

在很多情况下,通过将 Lambda 表达式内联在使用处, 可以消除运行时消耗。

翻看 Kotlin 的 Standard.kt 可以发现它里面的函数 with、apply、run、let 等都使用了 inline。

再举一个例子,对 Closeable 进行扩展,让它支持Java的 try-with-resources特性。

 
  
  1. inline fun <T : Closeable?, R> T.use(block: (T) -> R): R {

  2.    var closed = false

  3.    try {

  4.        return block(this)

  5.    } catch (e: Exception) {

  6.        closed = true

  7.        try {

  8.            this?.close()

  9.        } catch (closeException: Exception) {

  10.        }

  11.        throw e

  12.    } finally {

  13.        if (!closed) {

  14.            this?.close()

  15.        }

  16.    }

  17. }

该方法已经在 https://github.com/fengzhizi715/SAF-Kotlin-Utils 中

总结

本文是该系列最后一篇文章,未来不会整理零碎的开发细节,转而会以体系化形式进行整理。

该系列的相关文章:

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

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

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

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



关注【Java与Android技术栈】

更多精彩内容请关注扫码

640?wx_fmt=jpeg


猜你喜欢

转载自blog.csdn.net/SLFq6OF5O7aH/article/details/80809700