Android 开发与 Kotlin
了解 Android 系统与应用
Android 系统架构

- Linux 内核层
为 Android 设备的各种硬件提供了底层的驱动(显示,音频,摄像,蓝牙,WIFI,电源…)
- 系统运行库层
一些C/C++库(SQLite,OpenGL,Webkit),一些 Android 运行时库,其中包含 Dalvik(-> ART) 虚拟机,它使得每一个Android应用都能运行在独立的进程中,并且拥有一个自己的虚拟机实例。相较于Java虚拟机,Dalvik 和 ART 针对手机内存、CPU 性能有限等情况做了优化处理。
- 应用框架层
提供各种 API 以供开发者构建自己的应用程序
- 应用层
所有安装在手机上的应用程序
Android 应用开发特色
四大组件
- Activity(应用程序的门面,用户看到的一切)
- Service(后台服务相关)
- BroadcastReceiver(接受电话,短信等广播消息,发送广播消息)
- ContentProvider(使应用程序之间共享数据的手段)
各种系统控件
提供了丰富的系统自带的控件效果(例如 Material Design 等等)
- SQLite数据库
自带了这种轻量级、运算速度极快的嵌入式关系型数据库,还可以通过 Android 封装好的 API 进行操作,方便了数据的存取
分析 Android 程序的项目结构
Project 视图下的目录结构

- .gradle 和 .idea
Android Studio自动生成的一些文件
- app/
代码、资源等内容,主要开发目录
- build/
编译时自动生成
- gradle/
gradle wrapper的配置文件,通过这个可以自动根据本地的缓存情况决定是否需要联网下载 gradle
- build.gradle
项目全局的gradle构建脚本,通常无需修改
app/src/main/
- res/
- drawable 开头的目录用来放图片
- mipmap 开头的目录用来放应用图标
- values 开头的目录用来放字符串、样式、颜色等配置
- layout 开头的目录用来放布局文件
- -hdpi, -xhdpi, -xxhdpi 标识不同分辨率,来适配不同设备
…
Android 的日志工具Log
Log.v(tag: String, msg: String)verbose 级别Log.d(...)debug 级别Log.i(...)info 级别Log.w(...)warn 级别Log.e(...)error 级别
Kotlin 之于 Java
Kotlin的语法更加简洁,对于同样的功能,使用 Kotlin 开发的代码量可能会比使用 Java 开发的减少 50% 甚至更多。另外,Kotlin 的语法更加高级,相比于 Java 比较老旧的语法,Kotlin 增加了很多现代高级语言的语法特性,使得开发效率大大提升。还有,Kotlin 在语言安全性方面下了很多工夫,几乎杜绝了空指针这个全球崩溃率最高的异常
变量和函数
| 关键字 | 说明 |
|---|---|
val |
value,用来声明一个不可变的变量(不可重新赋值),对应 Java 的 final |
var |
variable,用来声明一个可变的变量(可重新赋值),对应 Java 的非 final 变量 |
- 项目复杂时,可变变量会导致出现一些很难排查的问题,Kotlin 通过设计这两个关键字,使开发者主动思考设计变量的可变性。一个好的习惯是,永远优先使用 val,仅当无法满足需求时再使用 var
- 自动类型推导
1 | val a = 10 |
- 函数声明
1 | fun methodName(param1: Int, param2: Int): Int { |
- 简化写法:当函数体只有一行
1 | fun largerNumber(num1: Int, num2: Int): Int = max(num1, num2) |
根据类型推导机制,进一步简化
1 | fun largerNumber(num1: Int, num2: Int) = max(num1, num2) |
逻辑控制
if
用法与 Java 几乎相同,额外特性:Kotlin 中的 if 带返回值
原代码
1 | fun largerNumber(num1: Int, num2: Int): Int { |
简化到最后
1 | fun largeNumber(num1: Int, num2: Int) = if (num1 > num2) num1 else num2 |
when
更加强大的 switch
1 | fun getScore(name: String) = when (name) { |
类型匹配功能
1 | fun checkNumber(num: Number) = when (num) { |
when 还可以不带参数
1 | fun getScore(name: String) = when { |
for-in
- 区间的定义
1 | val range = 0..10 // [0, 10] |
循环体
1 | val count: Int = 2 |
此外 for-in 还可以遍历数组、集合等
面向对象
- 创建类,定义方法,并实例化
1 | class Person { |
- 关于继承:Kotlin 默认所有非抽象类都是不可以被继承的,因此需要额外关键字
open
1 | // open Person类 |
- 主构造函数(init 中用来存放主构造函数的逻辑)
1 | class Student(val sno: String, val grade: Int) : Person() { |
根据规定,构造函数必须调用父类的构造函数,因此,若 Person 定义如下
1 | open class Person(val name: String, val age: Int) {} |
则创建子类时
1 | class Student(val sno: String, val grade: Int, name: String, age: Int) : |
- 次构造函数:Kotlin规定,当一个类既有主构造函数又有次构造函数时,所有的次构造函数都必须调用主构造函数(包括间接调用)
1 | class Student(val sno: String, val grade: Int, name: String, age: Int) : |
- 接口:与 Java 几乎一致
创建接口
1 | interface Study { |
实现接口
1 | class Student(name: String, age: Int) : Person(name, age), Study { |
- 函数的可见性修饰符
| 关键字 | 说明 |
|---|---|
public |
(默认项)同 Java,对所有类都可见 |
private |
同 Java,只对当前类内部可见 |
protected |
只对当前类和子类可见 |
internal |
只对同一模块中的类可见 |
- 数据类与单例类
数据类通常需要重写equals()、hashCode()、toString()这几个方法,在 Java 中实现比较繁琐,在 Kotlin 中只需 data 关键字
1 | data class Cellphone(val brand: String, val price: Double) |
就可实现下面的操作
1 | fun main() { |
单例模式,即希望某个类在全局最多只能拥有一个实例,避免重复的对象,在 Java 中
1 | public class Singleton { |
Kotlin 写法:使用 object 关键字
1 | object Singleton { |