Android Kotlin 开发需知

变量延迟加载

// 某些成员变量在声明时无法初始化,且不想使用可空类型(也就是带?的类型)。可使用 lateinit 和 by lazy

    // 不知道具体值,后面再赋值使用;所以必须var
    lateinit var name: String

    // 知道具体值,用到的时候再加载,表示不可变的值,所以必须val
    //  {}中的最后一行代码返回初始化的结果,加载时机为第一次调用常量的时候,且只会加载一次
    private val book by lazy {
        LogUtil.i("这行代码不会影响book赋值")
        "Android"
    }

 访问权限修饰符

    public:      公开,可见性最大,哪里可以引用  Kotlin 的类默认是 public 的
    private:     私有,可见性最小,根据声明位置不同可分为类中可见和文件中可见
    protected:   保护,相当于private+ , 子类可见
    internal:    内部,仅对module内可见

构造方法,init代码块

/**
 * 构造函数单独用了一个 constructor 关键字来和其他的 fun 做区分,分主构造和次构造
 * 如果类中有主构造器,所有次构造器都需要通过this关键字调用主构造器
 *
 * 从主构造器的特性出发,一旦在类中声明了主构造器,就包含两点:
 *     必须性:创建类的对象时,不管使用哪个构造器,都需要主构造器的参与
 *     第一性:在类的初始化过程中,首先执行的就是主构造器
 */
class User constructor(var name: String) {

    // init 代码块是先于次构造器执行的。
    init {
        // 如果把主构造器看成身体的头部,那么 init 代码块就是颈部,次构造器就相当于身体其余部分
    }

    // 直接调用主构造器
    constructor(name: String, age: Int) : this(name)

    // 通过上一个次构造函数,间接调用主构造器
    constructor(name: String, age: Int, id: Int) : this(name, age) {}
    
}

 constructor 关键字省略,私有,参数

// 主构造器中 constructor 关键字如果没有被 可见性修饰符 或 注释 标注可以省略
class User(var name: String) {
    constructor(name: String, age: Int) : this(name)
}

// 主构造器被修饰为私有的,外部就无法调用该构造器
class User private constructor(var name: String) {
}
// 主构造函数里面声明属性,前面加 var / val 构造参数同时成为成员变量
class User(var name: String) {
}

// ↑↓ 上下等价  
class User(name: String) {
    var name: String = name
}

静态方法

一共三种实现方式:①object ②伴生对象 ③顶层函数

/**
 * 当用 object 声明一个类时,表明这个类是一个单例类,可继承其他类
 * object 可以定义在全局也可以在类的内部使用
 * object声明不能用在方法和inner内部类中,但是能嵌套在其他object声明和嵌套类中
 * object 定义后即刻实例化,因此 object 不能有定义构造函数
 */
object SystemUtil{
}


/**
 * 和 object 不同, companion object 的定义完全属于类的本身,
 * 因此 companion object 不能脱离类而定义在全局之中。
 * 类似 Java 里的 static 变量
 */
class ScreenUtil {

    // companion object 修饰为伴生对象,伴生对象在类中只能存在一个
    companion object {

    }

}

真实项目中推荐的写法是使用伴生对象和 object 关键字结合的方式,示例如下:

class UmengEventUtil {

    companion object {
        @JvmStatic
        fun getInstance(): UmengEventUtil {
            return Holder.instance
        }
    }

    private object Holder {
        val instance = UmengEventUtil()
    }

    fun onRegister(mContext: Context) {
        MobclickAgent.onEvent(mContext, "__cust_event_1")
    }
    
}

顶层声明 top - level property / function

又称顶层函数,直接在文件中定义函数和属性,这种顶层函数不要声明在module内最顶层的包中,至少要在一个包中

/*
顶层声明属于 package,不在 class/object 内
属性和函数,不属于任何 class,而是直接属于 package
它和静态变量、静态函数一样是全局的,用起来更方便:在其它地方用的时候,类名都不用写
*/

fun stringToDouble(money: String): Double {
    return money.toDouble()
}

get,set 方法

// 默认kotlin已自动生产set,get方法,可省略
class User() {
     var name: String? = null
        set(value) {
            field = value
        }
        get() = field
}

// 上下等价   ↑↓
class User{
     var name: String? = null
}
// 如只想让外部使用,不想外部set,可在set前面添加private将set方法私有化
class User {
    var name: String
        private set
    
    init {
        name = "设置name值,外部只能调用get方法"
    }
}

数据类

相比JavaBean手动生成各种方法,kotlin data class要简单很多

/**
 *  var user = User("zs",18,"10001")
 * 自动生成
 * toString()       LogUtil.e("user.toString = $user")
 * copy()           var user2 = user.copy(id = 2)
 * equals()         user.equals(user2) 输出 true
 * hashCode()       user.hashCode 输出内存地址
 * componentN()     解构声明   val (name, age, code) = User("zs", 0, "1001")
 */
data class User(
    var name: String,
    var age: Int,
    var code: String
)

扩展函数

// 原本使用
fun dp2px(dp: Float): Float {
    return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, Resources.getSystem().displayMetrics)
}

dp2px(3.4f)

// 扩展函数
fun Float.dp2px(): Float {
    return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, this, Resources.getSystem().displayMetrics)
}

3.2f.dp2px()

 

持续更新中...

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章