Android Studio及Kotlin学习笔记
Book
Kotlin从零到精通 Android开发——欧阳燊
2018年4月第一版 清华大学出版社
书附录源码github链接
资源下载和内容勘误CSDN链接
书是在学校图书馆借的
20190628
第一章搭建Kotlin开发环境,安装过程基本和书上一致。安装AS的时候可以选择不安装virtual device,暂时都是在用自己的手机调试,没有虚拟设备需求。
安装SDK很方便,也自带了书中提到的Gradle插件。
Anko库配置的那一部分没有实现,猜测是因为我没有装Jetbrains的东西,不过暂时也没影响。
对xml布局有了一定了解,好像VB啊……坑的地方就是用可视化工具design出来的布局和实际run起来的布局很多不同,几乎全崩,还得老老实实写xml……
第二章数据类型,看了基本数据类型及其转换,Nothing Special。
20190629
继续第二章数据类型,关于数组的定义和基本方法有所了解。
插曲:顺手搜了一手怎么打包apk给别人用。
关于字符串,和基本类型的转换很方便,其中字符串的toBoolean方法只能转换字符串“true”和“false”。
数组常用的方法有indexOf
,substring
,replace
,split
等,其中split
方法的结果用List<String>
来存。用这几种基本方法可以完成很多操作。(越看越像VB……
Kotlin中,直接在字符串中加入$变量名
即可表示此处引用该变量的值。需要注意的是,这个符号在markdown里看来也是一个神奇的符号,写这一段的时候就乱码了好几次……真正需要注意的是,符号$后面跟变量名,系统会自动匹配最长的变量名;如果在取值之前还要先运算,则需用大括号把运算表达式给括起来;算了不抄书了截个图算了……
20190630
继续第二章,容器:集合Set,队列List,映射Map。莫名想起了算法竞赛的时候,使用集合、队列和映射的时候。
对于变量,val表示该变量不可更改,var表示该变量可更改。容器默认为只读,需要允许修改,就加上Mutable
前缀。所以有MutableSet
,MutableList
,MutableMap
。三者有共同的方法isEmpty
,isNotEmpty
,clear
,contains
,interator
,count
。
容器名称 | 初始化方法 |
---|---|
Set | setOf |
MutableSet | mutableSetOf |
List | listOf |
MutableList | mutableListOf |
Map | mapOf |
MutableMap | mutableMapOf |
集合的遍历,for-in遍历、迭代器遍历、forEach遍历。
其中迭代器遍历使用得带器的hasNext方法判断是否存在下一个节点,用next方法获得下一个节点的元素。
r = goodsMutSet.iterator() |
forEach遍历内部使用it指代每条记录。
goodsMutSet.forEach { desc = "${desc}名称:${it}\n" } |
集合用得不多,主要用List和Map吧。
List
MutableList的add方法把元素加到队尾,set元素修改指定位置的元素,removeAt方法允许删除指定位置的元素。遍历方法和set相同,还多了一种按元素下标循环遍历的方式。
//indices是队列的下标数组。如果队列大小为10,则下标数组的取值为0到9 |
还多了排序方法sortB:
//sortBy表示升序排列,后面跟的是排序条件 |
Map
常用方法containsKey
,containsValue
,put
(添加元素),remove
(通过键名来删除元素)。
初始化时,两种方法。一是Pair(键名,键值)
,二是键名 to 键值
。
遍历依旧三种方法,注意的是要访问元素的key属性和value属性获得键名或者键值。比如:
val iterator = goodsMutMap.iterator() |
forEach内部使用key指代每条记录的键,使用value指代每条记录的值。
goodsMutMap.forEach { key, value -> desc = "${desc}厂家:${key},名称:${value}\n" } |
第二章结束。
20190702
第三章,控制语句。
条件分支
条件分支最简单,包括两路分支以及多路分支。两路分支的时候,因为if语句允许有返回值,能直接简化为类似于三目运算符的形式。
多路分支中,when语句必须带上else,when/else也允许有返回值。牛逼的是,不用break,处理完一次就直接跳出。还可以引入变量或者具体的运算表达式进行判断,甚至可以是个范围:
tv_answer.text = when (count) { |
更牛逼的是,还可以进行类型判断……
var countType:Number |
循环
遍历循环有for-in循环和利用indices下标数组的循环。下标数组用法同List。
关于条件循环,kotlin在for-in循环中提供了until、step、downTo等关键字,但还是很乱很麻烦,所以更灵活的方案还是用do/while进行条件循环。
循环中可以用continue和break。
//发现该行是空串或者空格串,则忽略该行 |
我惊呆了,给循环加上@标记,想break几层循环就break几层……
var i:Int = 0 |
20190704
空安全
//strA.isNullOrEmpty() //非空串与可空串均可调用 |
区别是全为空格的串算作Blank而不算Empty。
声明可空字符串,加个问号。获取可空串的length要注意避免空指针,Kotlin引入了几种标记。
val strCanNull:String? |
等式判断
导入样例代码build时,提醒Unresolved reference: Date()
,怀疑是anko的问题,于是配置好了anko。然后发现还是不行,搞了半天import java.util.*
,就OK了。
特点:字符串也可用==
和!=
来判断相等否(结构相等)。还有另一种更严格的判断是引用相等:意思是除了值相等以外,还要求引用的地址(即储存地址)相等,表达式用===
和!==
。
类型判断:is
,!is
。检验数组中是否存在某个元素:in
,!in
。
第三章结束。
20190706
第四章——函数运用
函数基本方法
override fun onCreate(savedInstanceState: Bundle?) {} |
override在同一行表达重载操作。kotlin默认函数就是公开的,所以省略了关键词”public”。函数若无返回参数,则不用特别说明。关键词”fun”表示函数定义。声明输入参数用“变量名称:变量类型”格式,变量支持空安全机制。
函数声明返回值用fun main():Int
这种格式,即使不声明,也会有一个Unit类型的对象返回,可直接省略Unit声明。这只是为了让函数定义完全符合变量定义的形式,若需要具体的输入参数,则一样需要在函数里用return关键字来返回参数值。
默认参数:在声明输入参数时在其后面加上等号及其默认值。
命名参数:给指定的参数赋值。如 getFourBigDefault(second="活字印刷")
。
可变参数:声明参数时用vararg otherArray: String?
,vararg
表示其后的参数个数不确定,可变参数当成一个数组来解析。So,可以实现可变的数组参数,声明时也要加上vararg
前缀,调用时要注意:可输入多个数组变量,每个数组都使用arrayOf定义。
fun getFourBigArray(vararg otherArray: Array<String>):String { |
20190710
先整理一下之前搞的关于打包的技巧,参考了**这篇博客**。
在app的build.gradle中加了以下代码。
//release版本输出包名自动追加版本号和版本名称 |
几种特殊函数
注:Kotlin允许定义全局函数,即函数可在单独的kt文件中定义,然后其他地方也能直接调用。
泛型函数:在函数名称前面添加<T>
,表示以T声明的参数,其参数类型必须在函数调用时指定。把T换成其他的都行,只要前后对应。如:
fun <R> appendString(tag:String, vararg otherInfo: R?):String {} |
内联函数:fun setArrayNumber(array:Array<Number>) {}
不接受Array<Int>
或者Array<Double>
的入参,得指定泛型变量T来自于基类Number,即将T改为<reified T:Number>
,同时在fun
前面添加关键字inline
。如:
inline fun <reified T : Number> setArrayStr(array:Array<T>) {} |
简化函数:Kotlin把函数当作一种特殊变量,则允许通过等号给函数这个变量进行赋值。所以阶乘函数如下:
fun factorial(n:Int):Int = if (n <= 1) n else n* factorial(n - 1) |
尾递归函数:指函数末尾的返回值重复调用了自身函数,要在fun
前面加上关键字tailrec
。如:
tailrec fun findFixPoint(x: Double = 1.0): Double |
高阶函数:允许将函数表达式作为输入参数传进来,就形成了高阶函数。
//允许将函数表达式作为输入参数传进来,就形成了高阶函数,这里的greater函数就像是个变量。 |
插一段关于Kotlin 包和 import 语句使用,复制样例代码到测试工程中时遇到了这个报错,因为import的package和包里声明的package以及文件目录表示的package三者不匹配。
增强系统函数
扩展函数:例子如下:
//扩展函数结合泛型函数,能够更好地扩展函数功能 |
扩展高阶函数:高阶函数+泛型函数+扩展函数的功能,很强。和前面对比着看。
//给高阶函数进行扩展,形成数组的扩展函数 |
日期时间函数:基本上每个Android工程都需要一个类似的工具类来获得不同格式的字符时间串,使用扩展函数可以实现。例如:
//返回开发者指定格式的日期时间字符串 |
//关键字object用来声明单例对象,就像Java中开发者自己定义的Utils工具类。 |
调用变得简洁了很多。第四章结束。
20190711
跳过了书,直接开始搞蓝牙开发。
参考资料:
然后放到了github上,**链接**。不过想了一下,比赛还在初期,就不开源了吧。比赛结束再开源,希望能取得一个好成绩。值得一提的是,在AndroidStudio的工程目录自动生成了gitignore文件,忽略了不必要的配置和build文件。
目前实现了app控制手机蓝牙的开关、显示该手机已配对的蓝牙设备、以及对特定的蓝牙设备(即目前用来测试的HC-05蓝牙片子)进行连接/断开连接,同时完成了手机端到HC-05的数据传输。下一步是实现app的数据接收及处理。
20190714注:这个牛逼的测试程序有很多bug,我太年轻了,对蓝牙开发的理解还是不够。
20190714
前两天没有做笔记,因为发现开发蓝牙太麻烦了,还是用已有的框架吧,然后就折腾了两天……
因为经典蓝牙的相关框架实在太少,遂转战BLE,这次准备用BLE了。其余内容在项目文档里写了,链接
旧的测试项目一样。
20190717
第六章 6.1没啥好说。