A singleton

When writing singletons in Java, you can write several. Similarly, you can write multiple singletons using Kotlin. What I’ve described here is a way to implement singletons using delegate properties.

First, Kotlin supports the delegate pattern at the syntactic level.

The delegation pattern is one of the basic techniques in software design patterns. In delegate mode, there are two objects involved in processing the same request, and the receiving object delegates the request to another object to handle it. While the delegate pattern is a basic technique, many other patterns, such as the state pattern, the policy pattern, and the visitor pattern, essentially adopt the delegate pattern in more specific situations. The delegate pattern allows us to replace inheritance with aggregation.

For some very common properties, although we can implement them manually every time we need them, it is better to implement them all at once and put them in a library. In other words, operations on its property values are no longer dependent on its own getter()/setter() methods, but are entrusted to a proxy class so that the property in each usage class can be managed uniformly by the proxy class. This way is the delegate property.

The Not NULL property is one of a series of standard delegates in Kotlin’s standard library. It’s going to have a nullable variable and it’s going to assign a real value when we set this property. If the value is not assigned before it is retrieved, it throws an exception.

The Application singleton can also be implemented by lazy. We use the not NULL delegate to implement the Application singleton.

class App : Application() {
    companion object {
        var instance: App by Delegates.notNull()
    }

    override fun onCreate(a) {
            super.onCreate()
            instance = this}}Copy the code

Ii. Package Extras

Use the ExtrasDelegate to encapsulate Extras

import android.support.v4.app.Fragment
import android.support.v7.app.AppCompatActivity
import kotlin.reflect.KProperty

/ * * * *@FileName:
 *          com.safframework.delegate.extras.Extras.kt
 * @author: Tony Shen
 * @date: the 2018-06-11 23:56 *@versionV1.0 < Describes the current version functions > */
class ExtrasDelegate<out T>(private val extraName: String, private val defaultValue: T) {

    private var extra: T? = null

    operator fun getValue(thisRef: AppCompatActivity, property: KProperty< * >): T {
        extra = getExtra(extra, extraName, thisRef)
        returnextra ? : defaultValue }operator fun getValue(thisRef: Fragment, property: KProperty< * >): T {
        extra = getExtra(extra, extraName, thisRef)
        returnextra ? : defaultValue } }fun <T> extraDelegate(extra: String.default: T) = ExtrasDelegate(extra, default)

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

@Suppress("UNCHECKED_CAST")
private fun <T> getExtra(oldExtra: T? , extraName:String, thisRef: AppCompatActivity): T? = oldExtra ? : thisRef.intent?.extras?.get(extraName) as T?

@Suppress("UNCHECKED_CAST")
private fun <T> getExtra(oldExtra: T? , extraName:String, thisRef: Fragment): T? = oldExtra ? : thisRef.arguments? .get(extraName) as T?
Copy the code

After wrapping, pass parameters in MainActivity to jump to other activities.

import android.content.Intent
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import com.safframework.delegate.R
import com.safframework.delegate.domain.User
import com.safframework.ext.click
import kotlinx.android.synthetic.main.activity_main.*

/ * * * *@FileName:
 *          com.safframework.delegate.activity.MainActivity.java
 * @author: Tony Shen
 * @date: the 2018-06-13 12:03 *@versionV1.0 < Describes the current version functions > */
class MainActivity:AppCompatActivity() {

    public override fun onCreate(savedInstanceState: Bundle?). {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        initViews()
    }

    private fun initViews(a) {

        text1.click{

            val intent = Intent(this@MainActivity, Demo4ExtrasDelegateActivity::class.java)
            val u = User("Tony"."123456")
            intent.putExtra("user",u)
            intent.putExtra("string"."just a test")
            startActivity(intent)
        }

        text2.click {

            val intent = Intent(this@MainActivity, Demo4PrefsDelegateActivity::class.java)
            startActivity(intent)
        }
    }
}
Copy the code

The click function here is already described in Kotlin efficient Development of Android Apps (part 2), so I won’t repeat it.

Demo4ExtrasDelegateActivity accept passed from MainActivity parameters.

import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import com.safframework.delegate.domain.User
import com.safframework.delegate.extras.extraDelegate
import com.safframework.log.L

/ * * * *@FileName:
 *          com.safframework.delegate.activity.Demo4ExtrasDelegateActivity.java
 * @author: Tony Shen
 * @dateWhen * : 2018-06-13@versionV1.0 < Describes the current version functions > */
class Demo4ExtrasDelegateActivity: AppCompatActivity() {

    private val user: User? by extraDelegate("user")
    private val s:String? by extraDelegate("string")

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

        L.json(user)
        L.i(s)
    }
}
Copy the code

For any object type passed, Extras can be obtained as follows. Just make sure the extra key is correct.

    private val user: User? by extraDelegate("user")
    private val s:String? by extraDelegate("string")
Copy the code

Like Extra, SharedPreferences can also be encapsulated using property delegation.

Three infix.

Infix expression is a general arithmetic or logical formula representation in which the operator is in the middle of the operand in the form of an infix. Infix expressions allow us to use a word or letter as an operator (which is essentially a function call), ignoring the dots and parentheses of the call.

The infix expression of Kotlin must meet the following conditions:

  1. Use infix
  2. Only one parameter
  3. Its arguments must not accept a variable number of arguments and must not have default values.

Such as:

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

infix fun Int. Add(i:Int):Int = this + i

fun main(args: Array<String>) {

    println(5 add 10)
    println(510)}Copy the code

Execution result:

15
15
Copy the code

The most classic example of using infix expressions in Kotlin is using kxDate to manipulate a date. Kxdate making address: https://github.com/yole/kxdate

val twoMonthsLater = 2.months.fromNow
val yesterday = 1.days.ago
Copy the code

Is equivalent to:

val twoMonthsLater = 2 months fromNow
val yesterday = 1 days ago
Copy the code

As you can see, infix expressions can make code look more like natural language.

4. The inline

Kotlin’s natural support for functional programming features higher-order functions and lambdas.

Using higher-order functions comes with some run-time efficiency losses: Each function is an object, and each one captures a closure. These are the variables that will be accessed inside the function itself. Memory allocation (for function objects and classes) and virtual calls introduce runtime overhead.

Functions with the inline modifier can be inlined by copying the body of the function to the point of call from the compiler’s perspective. * * *

In many cases, you can eliminate runtime consumption by inlining Lambda expressions where they are in use.

If you look at Kotlin’s standard. kt, you can see that the functions with, apply, run, let, and so on are inline.

As another example, extend Closeable to support Java’s try-with-resources feature.

inline fun 
        T.use(block: (T) -> R): R {
    var closed = false
    try {
        return block(this)}catch (e: Exception) {
        closed = true
        try {
            this? .close() }catch (closeException: Exception) {
        }
        throw e
    } finally {
        if(! closed) {this? .close() } } }Copy the code

This method has been in the https://github.com/fengzhizi715/SAF-Kotlin-Utils

conclusion

This is the final article in the series, and instead of sorting out the piecemeal development details, it will be done in a systematic way.

Related articles in this series:

Developing Android Apps efficiently with Kotlin (part 4)

Developing Android Apps efficiently with Kotlin (part 3)

Developing Android Apps efficiently with Kotlin (part 2)

Developing Android Apps efficiently with Kotlin (1)


Java and Android technology stack: weekly updates push original technical articles, welcome to scan the public qr code below and follow, look forward to growing with you and progress together.