kotlin开发总结

字符串格式化

  • String.format(“%02d”, 6) 少于两位数高位补0
  • String.format(“%2d”, 6) 少于两位数高位补空格
  • String.format(“%.2f”, 3.121415926) 保留两位小数

使用java class类型对象

intent中传入class需要java class

companion object {
        fun start(context: Context) {
            context.startActivity(Intent(context, ShoppingCartActivity::class.java))
        }
    }

单例模式

定义

object CartContainer {
fun setCallBack(callback: Callback): CartContainer {
        this.callback = callback
        return this
    }
}

单例调用

CartContainer.setCallBack()

集合操作

  1. 对象集合某字段合并成字符串
    合并prodCrowds集合中所有crowd对象crowdText 字段

    fun getProdCrowdsName(): String = 
        prodCrowds.joinToString(",") { crowd -> crowd.crowdText }
  2. 一个类集合转另一个类集合
    从Sku类集合list获取CartNumBody类集合

    val list = adapter.list.map { SkuApi.CartNumBody(it.prodId, it.prodNum, true) }
  3. 集合统计double类型数据之和
    统计skuList集合中sku的价格之和,这里使用BigDecimal来统计,直接使用+会有差错,sumByDouble{}使用的是+操作。

    var totalPrice = 0.0
    skuList.asSequence()
        .filter { it.isSelect }
        .forEach { totalPrice = BigDecimalUtil.add(totalPrice, it.getTotalPrice()) }

    BigDecimalUtil.add方法如下,传入BigDecimal需要转String类型,double类型似乎也会出些小差错。

    public static double add(double value1, double value2) {
        return new BigDecimal(String.valueOf(value1)).add(new BigDecimal(String.valueOf(value2))).doubleValue();
    }

POJO数据类

定义

data class Sku(
    @SerializedName("prod_id") var prodId: Long = 0,
    @SerializedName("prod_name") var prodName: String? = null) : Serializable {
    //方法定义
}

克隆对象使用sku.copy()可复制所有值,基本类型会复制,引用类型会使用引用地址,即使用的浅拷贝


回调

不需要再定义多余接口,直接定义函数类型变量:

private var callback: (() -> Unit)? = null

定义set方法

fun setCallBack(callback: () -> Unit): CartContainer {
    this.callback = callback
    return this
}

调用上面的回调方法

callback?.let { it() }

设置回调,obj为上边定义回调的对象

obj.setCallBack { 方法体  }

带参数的回调

定义

var onConfirmClickListener: ((categoryId: Long?, tagIdList: MutableList?, crowdIdList: MutableList?) -> Unit)? = null

调用上面的回调方法

onConfirmClickListener?.let { it(categoryId, tagIdList, crowdIdList) }

设置回调,obj为上边定义回调的对象

obj.onConfirmClickListener = { categoryId, tagIdList, crowdIdList ->
            mCategoryId = categoryId
            mTagIdList = tagIdList
            mCrowdIdList = crowdIdList

            skuDrawerLayout.closeDrawers()
            getData(Constants.PAGE_INDEX_START, mCategoryId, mTagIdList, mCrowdIdList)
            skuSwipeRefreshLayout.isRefreshing = true
        }

kotlin使用Java类中的回调

java类回调为接口

setOnConfirmClick(object : OnConfirmClick {
    override fun onClick() {
        方法体
    }
})

java类回调为抽象类

setOnConfirmClick(object : OnConfirmClick() {
    override fun onClick() {
        方法体
    }
})

延迟初始化

定义变量

private lateinit var adapter: SkuAdapter

在任何可初始化方法中初始化,可初始化多次

adapter = SkuAdapter(activity)

懒性初始化

延迟初始化,其在第一次使用时初始化,下面的lazy为函数

val mDialogManager: DialogManager by lazy {
    DialogManager(this)
}

解析:上面lazy默认返回SynchronizedLazyImpl类实例,该对象持有属性value,get方法用懒加载方式实现,如下边代码,其实现是判断另一个属性_value是否初始化,已初始化返回值,否则调用initializer!!()即上面代码DialogManager(this),注意DialogManager(this)实际上是()->DialogManager(this)lambda表达式。我们使用mDialogManager变量实际上调用的是SynchronizedLazyImpl对象里的value.get()方法

override val value: T
    get() {
        val _v1 = _value
        if (_v1 !== UNINITIALIZED_VALUE) {
            @Suppress("UNCHECKED_CAST")
            return _v1 as T
        }

        return synchronized(lock) {
            val _v2 = _value
            if (_v2 !== UNINITIALIZED_VALUE) {
                @Suppress("UNCHECKED_CAST") (_v2 as T)
            }
            else {
                val typedValue = initializer!!()
                _value = typedValue
                initializer = null
                typedValue
            }
        }
    }

lazy函数可指定线程安全模式
- LazyThreadSafetyMode.SYNCHRONIZED 有同步锁,只会在一个线程初始化,因而时线程安全的
- LazyThreadSafetyMode.PUBLICATION未初始化时可能会初始化多次,一旦初始化便不再初始化,其值只取第一次初始化的值
- LazyThreadSafetyMode.NONE 可能会初始化多次,多线程中行为不确定,建议只用于单个线程初始化


观察属性值变更

name变量初始化为abc

var name: String by Delegates.observable("abc") { property, oldValue, newValue ->
    println("$property $oldValue->$newValue")
}

修改变量name为mz会调用上面observable的lambda表达式property, oldValue, newValue ->
println("$property $oldValue->$newValue")

name = "mz"

解析:oboservable返回ObservableProperty对象,该对象
内部实现了setValue方法,如下边代码,beforeChange永远返回true,所以afterChange会被调用,afterChange指向的是上边指定的lambda表达式property, oldValue, newValue -> println("$property $oldValue->$newValue")

public override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
    val oldValue = this.value
    if (!beforeChange(property, oldValue, value)) {
        return
    }
    this.value = value
    afterChange(property, oldValue, value)
}

使用Delegates.vetoable可在属性值变更前做处理操作,传入的lambda表达式赋值给beforeChange函数,需要返回boole值,返回true时不修改该变量,返回false修改该变量

同样可以同时观察变更前和变更后做处理操作,beforeChange返回true时不会调用afterChange函数

var age: Int by object : ObservableProperty<Int>(25) {
    override fun afterChange(property: KProperty<*>, oldValue: Int, newValue: Int) {
        super.afterChange(property, oldValue, newValue)
        println("$property $oldValue->$newValue")
    }

    override fun beforeChange(property: KProperty<*>, oldValue: Int, newValue: Int): Boolean {
        println("$property $oldValue->$newValue")
        return super.beforeChange(property, oldValue, newValue)
    }
}

by关键字解析见文档 中 英


函数定义

可定义在类体中、方法体中

fun refreshData() = getData(Constants.PAGE_INDEX_START, mCategoryId, mTagIdList, mCrowdIdList)

扩展函数

在Activity扩展showSnackBar方法,在Activity子类中可直接调用showSnackBar()方法

fun Activity.showSnackBar(view: View, msg: String, time: Int = Snackbar.LENGTH_SHORT) {
    Snackbar.make(view, msg, time).show()
}

内联函数

代码调用处 context.obtainString(R.id.text)会替换成下边方法的方法体代码this.resources.getString(resId)

inline fun Context.obtainString(resId: Int): String = this.resources.getString(resId)

禁用内联

如下代码,内联函数不仅会去掉valid函数,也会去掉body函数替换成body函数体的代码,会使body不再是一个函数,因而无法用于下边定义的submit高阶函数参数

inline fun  valid(lock: Lock, body: () -> T): T {
        lock.lock()
        try {
            submit(body) //内联后body不是函数,无法传给submit函数
            return body()
        } finally {
            lock.unlock()
        }
}

//submit高阶函数
fun <T> submit(body: ()-> T){

}

可以使用noinline关键字禁止内联

inline fun  valid(lock: Lock, noinline body: () -> T): T {
        lock.lock()
        try {
            submit(body) //body禁止内联后可传入submit函数
            return body()
        } finally {
            lock.unlock()
        }
}

fun <T> submit(body: ()-> T){
}

线程操作和更新UI

添加依赖包

api "org.jetbrains.anko:anko-common:0.10.2"

Activity中代码

doAsync {
    //子线程中执行

    uiThread {
        //UI线程中执行,如Activity销毁则不会执行
    }
}

参考文档 中 英

你可能感兴趣的:(kotlin)