kotlin学习笔记-1

1.声明变量

val   不可变的变量(但如果是对象变量自身的属性是var则该属性仍然可变)
var   可变的变量

2.函数可见性修饰符

public     所有类可见(默认)
private    当前类可见
protected  当前类、子类可见
internal   同一模块中可见

3.Lambda编程

Lambda {参数名1:参数类型, 参数名2:参数类型 -> 函数体}
listof()        不可变的集合
mutableListof() 可变的集合(map同)

4.kotlin空指针检查

?.       非空判断才执行后续的代码,== if(){}
?:       val c = a ?: b   a不为空返回a否则返回b(类似三目运算,只是带返回值)
!!       非空断言工具(确信不为空,关闭非空检查)
?.let{}  可以处理括号中全局变量的判空问题

5.字符串内嵌表达式

"value == $value"       等于 "value == " + value    (value 为String)
"name == ${obj.name}"   等于 "name == " + obj.name

6.kotlin 区间

val rang1 = 0..10         [0, 10] 闭区间
val rang2 = 0 until 10    [0, 10) 左闭右开区间
val rang3 = 10 downTo 1   [10, 1] 闭区间

7.杀掉当前进程

android.os.Process.killProcess(android.os.Process.myPid())

8.kotlin标准函数

1)/** 标准函数 with **/
val list = listOf("Apple", "Banana", "Orange", "Pear", "Grape", "Watermelon")
val builder = StringBuilder()
builder.append("Start eating fruits.\n")
for (fruit in list){
    builder.append(fruit).append("\n")
}
builder.append("Ate all fruits.")
val result = builder.toString()
println(result)

val result2 = with(StringBuilder()){
    append("Start eating fruits.\n")
    for (fruit in list){
        append(fruit).append("\n")
    }
    append("Ate all fruits.")
    toString()
}
println(result2)

val result = with(obj){
	// 这里是obj的上下文
	"value" // with函数的返回值
}
2)/****** 标准函数 run **/
val result3 = StringBuilder().run {
    append("Start eating fruits.\n")
    for (fruit in list){
        append(fruit).append("\n")
    }
    append("Ate all fruits.")
    toString()
}
println(result3)

val result = obj.run {
	// 这里是obj的上下文
	"value" // run函数的返回值
}
3)/****** 标准函数 apply **/
apply函数只能返回obj本身
val result4 = StringBuilder().apply {
    append("Start eating fruits.\n")
    for (fruit in list) {
        append(fruit).append("\n")
    }
    append("Ate all fruits.")
}
println(result4.toString())

val result = obj.apply {
	// 这里是obj的上下文
}
// result == obj

9.kotlin高阶函数(261~271)

如果一个函数接收另一个函数作为参数,或者返回值的类型是另一个函数,则该函数称为高阶函数,语法规则:
(String, Int) -> Unit
-> 左侧声明该函数接收什么参数,多个参数逗号隔开,如果不接收参数空括号;右侧声明函数的返回值,如果没有返回值使用Unit(相当于Java中void)
示例:
fun num1AndNum2(num1: Int, num2: Int, operation: (Int, Int) -> Int): Int {
    val result = operation(num1, num2)
    return result
}

fun plus(num1: Int, num2: Int): Int {
    return num1 + num2
}

fun minus(num1: Int, num2: Int): Int {
    return num1 - num2
}

fun main() {
    val num1 = 100
    val num2 = 80
    val result1 = num1AndNum2(num1, num2, ::plus)
    val result2 = num1AndNum2(num1, num2, ::minus)
    println("result1 == $result1")
    println("result2 == $result2")
}
::plus 和 ::minus 是一种函数引用方式,表示将 plus()minus() 函数作为参数传递给 num1AndNum2() 函数

Lambda表达式写法:
fun main() {
    val num1 = 100
    val num2 = 80
    val result3 = num1AndNum2(num1, num2) { n1, n2 ->
        n1 + n2
    }
    val result4 = num1AndNum2(num1, num2) { n1, n2 ->
        n1 - n2
    }
    println("result3 == $result3")
    println("result4 == $result4")
}
1)inline 内联函数
每使用一次Lambda表达式都会创建一个新的匿名类实例,会造成额外的内存和性能开销,kotlin提供了“内联函数”来解决使用Lambda表达式带来的运行时开销(266页):
定义高阶函数时加上inline关键字声明
inline fun num1AndNum2(num1: Int, num2: Int, operation: (Int, Int) -> Int): Int {
    val result = operation(num1, num2)
    return result
}

内联函数原理:kotlin编译器会将内联函数中的代码在编译时自动替换到调用它的地方,也就不存在运行时的开销。
2)noinline(非内联函数)与crossinline
inline fun inlineTest(block1: () -> Unit, noinline block2: () -> Unit) {
}

fun printString1(str: String, block: (String) -> Unit) {
    println("printString begin")
    block(str)
    println("printString end")
}

inline fun printString2(str: String, block: (String) -> Unit) {
    println("printString begin")
    block(str)
    println("printString end")
}

fun main() {
    println("main start")
    val str = ""
    printString1(str) { s ->
        println("lambda start")
        if (s.isEmpty()) return@printString // 局部返回不再执行Lambda表达式剩余部分代码
        println(s)
        println("lambda end")
    }
    printString2(str) { s ->
        println("lambda start")
        // if (s.isEmpty()) return@printString // 局部返回不再执行Lambda表达式剩余部分代码
        if (s.isEmpty()) return // 全局返回,main后续都不再执行
        println(s)
        println("lambda end")
    }
    println("main end")
}

10.新知识

1)废弃kotlin-android-extensions编译器插件
1.4.20-M2版本开始废弃kotlin-android-extensions编译器插件,最新使用 viewBinding
// classpath "org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version"
// id 'kotlin-android-extensions'
2)kotlin定义内部类:inner class关键字
3)隐式Intent,不仅可以启动自身程序内activity,也可启动其他程序内activity
4)kotlin中常量:在companion object、单例类、顶层作用域中使用 const 关键字 声明常量
class Money(val value: Int) {
    companion object{
        const val TAG = "TAG"
    }
}
5)kotlin数据类:关键字 data
data class CellPhone(val brand: String, val price: Double)
6)kotlin单例类:关键字 object
object PopManager{
    fun methord(){
        // todo 
    }
}
7)在一个IP网络范围中,最大的IP地址是被保留作为广播地址来使用的:

比如:某网络IP范围是192.168.0.xxx,子网掩码是255.255.255.0,那么这个网络的广播地址就是192.168.0.255

8)lateinit :延迟初始化的变量
lateinit var str: String
指一个延迟初始化的变量
/*
在kotlin里面,如果在类型声明之后没有使用符号?,则表示该变量不会为null。但是这个时候会要求我们初始化一个值。有些时候,我们在声明变量的时候,并不能初始化这个变量。但是我们又想使用kotlin非null变量带来的便利,这个时候,你需要的就是lateinit了。它告诉编译器,这个变量会被初始化,并且不会为null,但是在声明这里,我暂时还不知道什么时候会被初始化。如果一个变量声明为lateinit,但是没有初始化,而又被使用了的话,会抛出一个异常UninitializedPropertyAccessException。
*/
9)TextView属性
android:autoLink 是否自动链接网址或邮箱地址;
android:autoText 自动检测错误;
android:bufferType 决定getText()返回的类型
android:capitalize 指定使用类型
android:cursorVisible 光标是否可见
android:digits 数字输入
android:drawableBottom 内容显示在文字的下边
android:drawableEnd 内容显示在文字的结尾
android:drawableLeft 内容显示在文字的左边
android:drawablePadding 内容和文字之间的空隙
android:drawableRight 内容显示在文字的右边
android:drawableStart 内容显示在文字的开始
android:drawableTop 内容显示在文字的上边
android:editable 编辑功能,能够使用输入法
android:editorExtras 编辑功能扩展,用户设置
android:ellipsize 椭圆区域的显示方式
android:ems 可以在更多系统上运行
android:fontFamily 字体风格
android:freezesText 冻结在光标位置
android:gravity 文字小于显示范围时,x和y轴方向的调整
android:height 文字像素高度
android:hint 文本空白时的提示语
android:imeActionId 激活输入法ID序号
android:imeActionLabel 激活输入法符号
android:imeOptions 输入法操作
android:includeFontPadding 足够空间容纳字体显示
android:inputMethod 指定输入法
android:inputType 选择输入法
android:lineSpacingExtra 额外的文字间距
android:lineSpacingMultiplier 额外的文字间距,乘数
android:lines 多行显示
android:linksClickable 点击链接
android:marqueeRepeatLimit 跑马灯重复限制
android:maxEms 最大系统兼容
android:maxHeight 最大文本高度
android:maxLength 最大文本长度
android:maxLines 最大文本行数
android:maxWidth 最大文本长度
android:minEms 最小系统兼容
android:minHeight 最小文本高度
android:minLines 最小文本行数
android:minWidth 最小文本宽度
android:numeric 支持数字输入
android:password 文本作为密码
android:phoneNumber 支持电话号码输入
android:privateImeOptions 私人输入操作
android:selectAllOnFocus 点击全部选中
android:shadowColor 阴影颜色
android:shadowDx 阴影水平偏移
android:shadowDy 阴影垂直偏移
android:shadowRadius 阴影半径
android:singleLine 单行显示
android:text 显示文本
android:textAllCaps 文本全部大写
android:textAppearance 基本的文字颜色,字体,大小,风格
android:textColor 文本颜色
android:textColorHighlight 文本高亮颜色
android:textColorHint 文本提示颜色
android:textColorLink 链接文本颜色
android:textIsSelectable 文本能够被选中
android:textScaleX 水平缩放参数
android:textSize 文本大小
android:textStyle 文本风格
android:typeface 文本字体
android:width 文本宽度
10)Any 是kotlin所有类的共同基类( == Java 中 Object)

11.扩展函数:ClassName.**

fun ClassName.methodName(param1: Int, param2: Int): Int {
	// todo
    return 0
}

fun Int.valueGreaterThan10000(): Boolean {
    return this > 10000
}

kotlin中的String的 .reverse()反转字符串,.capitalize()对首字母大写 等是kotlin自带的扩展函数

12.运算符重载:operator

class Money(val value: Int) {
    operator fun plus(money: Money): Money {
        val obj = this.value + money.value
        return Money(obj)
    }

    // 重载不限于对象
    operator fun plus(newValue: Int): Money {
        val obj = this.value + newValue
        return Money(obj)
    }
}

常用可重载运算符及关键字对应语法糖表达式及实际调用函数见书238/239页

13.广播机制

1)标准广播:

完全异步执行的广播,几乎同时接收,无法被截断

2)有序广播:

同步执行的广播,按优先级接收,可以被截断

3)常用系统广播:
Intent.ACTION_AIRPLANE_M 						关闭或打开飞行模式时的广播
Intent.ACTION_BATTERY_CH						充电状态,或者电池的电量发生变化 电荷级别改变,只能在代码注册
Intent.ACTION_BATTERY_LO 						电池电量低
Intent.ACTION_BATTERY_OK 						电池电量充足
Intent.ACTION_AIRPLANE_MODE_CHANGED 			关闭或打开飞行模式
Intent.ACTION_BATTERY_CHANGED 					充电状态,或者电池的电量发生变化 电荷级别改变,只能在代码注册
Intent.ACTION_BATTERY_LOW 						电池电量低
Intent.ACTION_BATTERY_OKAY 						电池电量充足 从电池电量低变化到饱满时会发出广播
Intent.ACTION_BOOT_COMPLETED 					开机广播:在系统启动完成后,这个动作被广播一次 只有一次
Intent.ACTION_CAMERA_BUTTON 					按下照相时的拍照按键时发出的广播 硬件按键
Intent.ACTION_CLOSE_SYSTEM_DIALOGS 				当屏幕超时进行锁屏时,当用户按下电源按钮,长按或短按(不管有没跳出话框),进行锁屏
Intent.ACTION_CONFIGURATION_CHANGED 			设备当前设置被改变时发出的广播 界面语言,设备方向,等 请参考Configuration.java
Intent.ACTION_DATE_CHANGED 						设备日期发生改变时
Intent.ACTION_DEVICE_STORAGE_LOW 				设备内存不足时发出的广播 此广播只能由系统使用,其它APP不可用
Intent.ACTION_DEVICE_STORAGE_OK 				设备内存从不足到充足时发出的广播 此广播只能由系统使用,其它APP不可用
Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE 	移动APP完成之后,发出的广播 移动是指:APP2SD
Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE 正在移动APP时,发出的广播 移动是指:APP2SD
Intent.ACTION_GTALK_SERVICE_CONNECTED 			Gtalk已建立连接时发出的广播
Intent.ACTION_GTALK_SERVICE_DISCONNECTED 		Gtalk已断开连接时发出的广播
Intent.ACTION_HEADSET_PLUG 						在耳机口上插入耳机时发出的广播
Intent.ACTION_INPUT_METHOD_CHANGED 				改变输入法时发出的广播
Intent.ACTION_LOCALE_CHANGED 					设备当前区域设置已更改时发出的广播
Intent.ACTION_MANAGE_PACKAGE_STORAGE 			表示用户和包管理所承认的低内存状态通知应该开始
Intent.ACTION_MEDIA_BAD_REMOVAL 				未正确移除SD卡 扩展卡已经从SD卡插槽拔出,但是挂载点 (mount point) 还没解除 (unmount)
Intent.ACTION_MEDIA_BUTTON 						按下”Media Button” 按键时发出的广播 有”Media Button” 按键的话(硬件按键)
Intent.ACTION_MEDIA_CHECKING 					插入外部储存装置 比如SD卡时,系统会检验SD卡,此时发出的广播
Intent.ACTION_MEDIA_EJECT 						已拔掉外部大容量储存设备发出的广播 不管有没有正确卸载
Intent.ACTION_MEDIA_MOUNTED 					插入SD卡并且已正确安装 扩展介质被插入而且已经被挂载
Intent.ACTION_MEDIA_NOFS 						拓展介质存在,但使用不兼容FS(或为空)的路径安装点检查介质包含在Intent.mData领域
Intent.ACTION_MEDIA_REMOVED 					外部储存设备已被移除,扩展介质被移除 不管有没正确卸载,都会发出此广播
Intent.ACTION_MEDIA_SCANNER_FINISHED 			已经扫描完介质的一个目录
Intent.ACTION_MEDIA_SCANNER_SCAN_FILE 			请求媒体扫描仪扫描文件并将其添加到媒体数据库
Intent.ACTION_MEDIA_SCANNER_STARTED 			开始扫描介质的一个目录
Intent.ACTION_MEDIA_SHARED 						扩展介质的挂载被解除 (unmount) 它已经作为 USB 大容量存储被共享
Intent.ACTION_PACKAGE_ADDED 					成功的安装APK 数据包括包名(最新安装的包程序不能接收到这个广播)
Intent.ACTION_PACKAGE_CHANGED 					一个已存在的应用程序包已经改变 包括包名
Intent.ACTION_PACKAGE_DATA_CLEARED 				清除一个应用程序的数据时发出的广播 清除包程序不能接收到这个广播
Intent.ACTION_PACKAGE_INSTALL 					触发一个下载并且完成安装时发出的广播 比如在电子市场里下载应用
Intent.ACTION_PACKAGE_REMOVED 					成功的删除某个APK之后发出的广播 正在被安装的包程序不能接收到这个广播
Intent.ACTION_PACKAGE_REPLACED 					替换一个现有的安装包时发出的广播(不管现在安装的APP比之前的新还是旧
Intent.ACTION_PACKAGE_RESTARTED 				用户重新开始一个包 重新开始包程序不能接收到这个广播
Intent.ACTION_POWER_CONNECTED 					插上外部电源时发出的广播
Intent.ACTION_POWER_DISCONNECTED 				已断开外部电源连接时发出的广播
Intent.ACTION_REBOOT 							重启设备时的广播
Intent.ACTION_SCREEN_OFF 						屏幕被关闭之后的广播
Intent.ACTION_SCREEN_ON 						屏幕被打开之后的广播
Intent.ACTION_SHUTDOWN 							关闭系统时发出的广播
Intent.ACTION_TIMEZONE_CHANGED 					时区发生改变时发出的广播
Intent.ACTION_TIME_CHANGED 						时间被设置时发出的广播
Intent.ACTION_TIME_TICK 						当前时间已经变化(正常的时间流逝) 每分钟都发送,只能通过来注册
Intent.ACTION_UID_REMOVED 						一个用户ID已经从系统中移除发出的广播
Intent.ACTION_UMS_CONNECTED 					设备已进入USB大容量储存状态时发出的广播
Intent.ACTION_UMS_DISCONNECTED 					设备已从USB大容量储存状态转为正常状态时发出的广播
Intent.ACTION_WALLPAPER_CHANGED 				设备墙纸已改变时发出的广播
Intent.ACTION_USER_PRESENT 						用户唤醒设备
Intent.ACTION_NEW_OUTGOING_CALL 				拨打电话

14.SQLite数据库存储

1)创建数据库表
数据类型:
integer		:整形
real		:浮点型
text		:文本类型
blob		:二进制类型

例如:
class MyDatabaseHelper(val context: Context, name: String, version: Int) :
    SQLiteOpenHelper(context, name, null, version) {
    private val createBook = "create table Book (" +
            " id integer primary key autoincrement, " +
            "author text, " +
            "price real, " +
            "pages integer, " +
            "name text)"
    private val createCategory = "create table Category (" +
            " id integer primary key autoincrement, " +
            "category_name text, " +
            "category_code integer)"
    override fun onCreate(db: SQLiteDatabase?) {
        db?.execSQL(createBook)
        db?.execSQL(createCategory)
        Toast.makeText(context, "Create succeeeded", Toast.LENGTH_SHORT).show()
    }
    override fun onUpgrade(db: SQLiteDatabase?, oldVersion: Int, newVersion: Int) {
        db?.execSQL("drop table if exists Book")
        db?.execSQL("drop table if exists Category")
        onCreate(db)
    }
}
val dbhelper = MyDatabaseHelper(this, "BookStore.db", 1) // 1 -> 2 才能重新触发 onCreate()
dbhelper.writableDatabase
2)数据库表操作
CRUD --> C:添加(create)		添加数据使用insert;
		 R:查询(retrieve)		查询数据使用select;
		 U:更新(update)		更新数据使用update;
		 D:删除(delete)		删除数据使用delete;

/**
 * 添加数据
 * @param table 		 表名
 * @param nullColumnHack 未指定添加数据时给某些可为空的列自动赋值null,一般直接传入null
 * @param values		 ContentValues对象提供了put()方法添加数据
 */
SQLiteDatabase.insert(String table, String nullColumnHack, ContentValues values)

/**
 * 更新数据
 * @param table 		 表名
 * @param values		 ContentValues对象提供了put()方法添加数据
 * @param whereClause 	 对应SQL语句where部分("name = ?"表示更新所有name等于?的行,?是占位符,具体值为参数四字符串数组)
 * @param whereArgs		 
 */
SQLiteDatabase.update(String table, ContentValues values, String whereClause, String[] whereArgs)

/**
 * 删除数据
 * @param table 		 表名
 * @param whereClause 	 对应SQL语句where部分("pages > ?"表示更新所有pages大于?的行,?是占位符,具体值为参数四字符串数组)
 * @param whereArgs		 
 */
SQLiteDatabase.delete(String table, String whereClause, String[] whereArgs)

数据类型:
integer :整形
real :浮点型
text :文本类型
blob :二进制类型

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐