Kotlin:Android开发技巧

816 阅读3分钟
原文链接: www.hchstudio.cn

Kotlin作为Android开发第一语言,然而身边做Android的大多还是使用java。Android转到Kotlin的趋势是必然的,公司隔壁部门已经全部使用Kotlin开发,我们在以后新的项目里,也会以Kotlin为主。关于Kotlin的知识,博主只是在去年下半年的时候看过官网的教程,也读了《Kotlin for Android Developers》,并写了一个练手项目,不过大半年过去了,要把以前学过的知识重新拿起来有点儿不易,于是总结了一些Kotlin在Android开发中的常用技巧。

Kotlin 基础技巧

单例

Kotlin是一种非常简单的语言,单例也是如此,这里列出两种常用的单例格式:
第一种:通过伴生对象+委托实现单例


                                                
class App : MultiDexApplication() {
    companion object {
        var INSTANCE: APP by Delegates.notNull()
    }
    override fun onCreate() {
        INSTANCE = this
    }
}


                                            

如上代码,在伴生对象中声名变量,并使用netNull委托避免Kotlin中的空异常检查,然后在onCreate中赋值

第二种:Kotlin关键字object


                                                
object CommonParam {
    var TAG = ""
}


                                            

Kotlin的写法是不是很简单粗暴。

Kotlin 委托

Kotlin中支持委托,有类委托、标准委托、也可以自定义委托。同学们可以看我之前的一篇博客:Kotlin委托

run、with、apply、alse、let、takeIf、repeat

字段 作用
T.run(block: () -> R) 运行函数并返回函数运行结果
T.with(receiver: T, block: T.() -> R) receiver作为block函数的this,返回函数运行结果
T.apply(block: T.() -> Unit) 运行函数,返回调用者自身
T.also(block: (T) -> Unit) 调用者作为函数it,执行函数并返回调用者自身
T.let(block: (T) -> R) 调用者作为block函数的this,返回函数运行结果
T.tabkeIf(predicate: (T) -> Boolean) 调用者满足函数的条件则返回自身,否则返回null
T.takeUnless(predicate: (T) -> Boolean) 与tabkeIf相反
repeat(times: Int, action: (Int) -> Unit) 从0遍历times,并运行action

拓展函数

Kotlin 可以对一个类的属性和方法进行扩展,且不需要继承或使用 Decorator 模式。
扩展是一种静态行为,对被扩展的类代码本身不会造成任何影响。
这里列出几个常用的拓展函数:


                                                
/**
 * Map<K, V?>类型转换为Array<out Pair<K, V>>类型
 */
fun <K, V : Any> Map<K, V?>.toVarargArray(): Array<out Pair<K, V>> =
        map({ Pair(it.key, it.value!!) }).toTypedArray()

/**
 * ImageView加载网络图片
 */
fun ImageView.loadImage(url: String) {
    CommonModule.picasso.load(url).into(this)
}

/**
 * anko.db框架中,数据库查询解析
 */
fun <T : Any> SelectQueryBuilder.parseList(parser: (Map<String, Any?>) -> T): List<T> =
        parseList(object : MapRowParser<T> {
            override fun parseRow(columns: Map<String, Any?>): T = parser(columns)
        })
fun <T : Any> SelectQueryBuilder.parseOpt(parser: (Map<String, Any?>) -> T): T? =
        parseOpt(object : MapRowParser<T> {
            override fun parseRow(columns: Map<String, Any?>): T = parser(columns)
        })


                                            

Anko 框架

Anko Commons

Anko Intent helpers:


                                                
startActivity(intentFor<SomeOtherActivity>("id" to 5).singleTop())


                                            

Anko Dialogs


                                                
toast("Hi there!")  // Toast
snackbar(view, "Hi there!")     // snacbar
alert("Hi, I'm Roy", "Have you tried turning it off and on again?") {       // alert
    yesButton { toast("Oh…") }
    noButton {}
}.show()
selector("Where are you from?", countries, { dialogInterface, i ->          // selector
    toast("So you're living in ${countries[i]}, right?")
})


                                            

AnkoLogger


                                                
class SomeActivity : Activity(), AnkoLogger {
    private fun someMethod() {
        info("London is the capital of Great Britain")
        debug(5) // .toString() method will be executed
        warn(null) // "null" will be printed
    }
}


                                            

Colors


                                                
0xff0000.opaque     // 转变为不透明的颜色
0x99.gray.opaque    // 转变为不透明的灰色
0xabcdef.withAlpha(0xCF) == 0xCFabcdef      // 设置透明度


                                            

Dimensions


                                                
dip(dipValue)       // dip转换为px
sp(spValue)         // sp转换为px
px2dip/px2sp        // px转换为dip或者sp


                                            

Anko Layouts

对于Anko Layouts的话,就相当于把xml的形式以DSL写在代码里,看起来很方便,不过楼主还是习惯了xml的方式,AnkoLayouts使用的比较少,想用的小伙伴们可以自行百度学习吧。

Anko SQLite

Anko提供了很方便的sql接口


                                                
class MyDatabaseOpenHelper(ctx: Context) : ManagedSQLiteOpenHelper(ctx, "MyDatabase", null, 1) {
    companion object {
        private var instance: MyDatabaseOpenHelper? = null

        @Synchronized
        fun getInstance(ctx: Context): MyDatabaseOpenHelper {
            if (instance == null) {
                instance = MyDatabaseOpenHelper(ctx.getApplicationContext())
            }
            return instance!!
        }
    }

    override fun onCreate(db: SQLiteDatabase) {
        // Here you create tables
        db.createTable("Customer", true, 
                    "id" to INTEGER + PRIMARY_KEY + UNIQUE,
                    "name" to TEXT,
                    "photo" to BLOB)
    }

    override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
        // Here you can upgrade tables, as usual
        db.dropTable("User", true)
    }
}

// Access property for Context
val Context.database: MyDatabaseOpenHelper
    get() = MyDatabaseOpenHelper.getInstance(getApplicationContext())


                                            

然后在需要用数据的地方,执行增删改查就好


                                                
database.use {
    // `this` is a SQLiteDatabase instance
}