Android notes——第一行代码笔记(第三版)

Android notes——第一行代码笔记(第三版)

Android notes——第一行代码笔记(第三版)

  • Android notes——第一行代码笔记(第三版)
  • 第2章——探究新语言,快速入门kotlin编程
    • 2.5 面向对象编程
      • 2.5.2 继承与构造函数
      • 2.5.4 数据类与单例类
    • 2.6 Lambda 编程
      • 2.6.0 什么是 Lambda 编程
      • 2.6.1 集合的创建与遍历
      • 2.6.2 集合的函数式 API
      • 2.6.3 Java 函数式 API 的使用
  • 第3章——先从看得到的入手,探究 Activity
    • 3.1 Activity 是什么
    • 3.2 Activity 基本用法
      • 3.2.1-3.2.3 创建 Activity、在 Activity 中加载 layout 布局、AndroidManifest中注册 Activity
      • 3.2.4 在 Activity 中使用 **Toast**,Toast 就是一个简单的提示消息~
        • 弃用的 `kotlin-android-extensions` 插件,获取布局中定义的元素、获取控件等实例—— `findViewById()` 的替代方法 ViewBinding
          • 引用内容——郭霖大神的博客中内容,方便自己查阅~
          • 1.在 Activity 中使用 ViewBinding
          • 2.在 Fragment 中使用 ViewBinding
          • 3.在 Adapter 中使用 ViewBinding
          • 4.对引入布局使用 ViewBinding
      • 3.2.5 在 Activity 中使用 Menu——就是菜单啦!P92
      • 3.2.6 销毁一个 Activity
    • 3.3 使用 `Intent` 在 Activity 之间穿梭
      • 3.3.0 何为 `intent`
      • 3.3.1 使用显式 `Intent`
      • 3.3.2 使用隐式 `Intent`
      • 3.3.3 更多隐式 `Intent` 的用法
      • 3.3.4 向下一个 Activity 传递数据
      • 3.3.5 返回数据给上一个 Activity
    • 3.4 Activity的生命周期
      • 3.4.1 返回栈
      • 3.4.2 Activity 状态
      • 3.4.3 Activity 的生存期
      • 3.4.4 体验 Activity 的生命周期
      • 3.4.5 Activity 被回收了怎么办
    • 3.5 Activity 的启动模式
      • 3.5.0 何为启动模式
      • 3.5.1 standard
      • 3.5.2 singleTop
      • 3.5.3 singleTask
      • 3.5.4 singleInstance
    • 3.6 Activity的最佳实践
      • 3.6.1 知晓当前是在哪一个 Activity
      • 3.6.2 随时随地退出程序
      • 3.6.3 启动 Activity 的最佳写法
      • 3.6.4 MHH总结
    • 3.7 Kotlin 课堂:标准函数和静态方法
      • 3.7.1 标准函数 with、run 和 apply
      • 3.7.2 定义静态方法

第2章——探究新语言,快速入门kotlin编程

2.5 面向对象编程

2.5.2 继承与构造函数

kotlin 知识点——Kotlin 中的 open 关键字

在 java 中允许创建任意的子类并重写方法任意的方法,除非显示的使用了 final 关键字进行标注。

而在 kotlin 的世界里面则不是这样,在 kotlin 中它所有的类默认都是 final 的,那么就意味着不能被继承,而且在类中所有的方法也是默认是 final 的,那么就是 kotlin 的方法默认也不能被重写。那么想在 kotlin 中继承父类应该怎么做呢?

  • 为类增加 open,class 就可以被继承了
open class Person{
   
    
} 
  • 为方法增加 open,那么方法就可以被重写了
open class Person{
   
    open fun eat(food: String) {
   
        
    }

}

open class Man:Person(){
   
    override fun eat(food: String) {
   
        super.eat(food)
        
    }
}

2.5.4 数据类与单例类

kotlin 知识点:单例类

想必你一定听说过单例模式吧,这是最常用、最基础的设计模式之一,它可以用于避免创建重 复的对象。比如我们希望某个类在全局最多只能拥有一个实例,这时就可以使用单例模式。

Java演示:

public class Singleton {
   
    private static Singleton instance;
    private Singleton() {
   }
    public synchronized static Singleton getInstance() {
   
        if (instance == null) {
   
            instance = new Singleton();
        }
        return instance;
    }
    public void singletonTest() {
   
        System.out.println("singletonTest is called.");
    }
}

这段代码其实很好理解,首先为了禁止外部创建Singleton的实例,我们需要用private关键 字将Singleton的构造函数私有化,然后给外部提供了一个getInstance()静态方法用于获 取Singleton的实例。在getInstance()方法中,我们判断如果当前缓存的Singleton实例 为null,就创建一个新的实例,否则直接返回缓存的实例即可,这就是单例模式的工作机制。 而如果我们想调用单例类中的方法,也很简单,比如想调用上述的singletonTest()方法, 就可以这样写:

Singleton singleton = Singleton.getInstance();
singleton.singletonTest();

在 Kotlin 中创建一个单例类的方式极其简单,只需要将 class 关键字改成 object 关键字即可。 现在我们尝试创建一个 Kotlin 版的 Singleton 单例类,右击com.example.helloworld 包 →New→Kotlin File/Class,在弹出的对话框中输入“Singleton”,创建类型选择“Object”,点 击“OK”完成创建,初始代码如下所示:

object Singleton {
   
}

现在 Singleton 就已经是一个单例类了,我们可以直接在这个类中编写需要的函数,比如加入 一个 singletonTest() 函数:

object Singleton {
   
    fun singletonTest() {
   
        println("singletonTest is called.")
    }
}

可以看到,在 Kotlin 中我们不需要私有化构造函数,也不需要提供 getInstance() 这样的静态 方法,只需要把 class 关键字改成 object 关键字,一个单例类就创建完成了。而调用单例类中的函数也很简单,比较类似于Java中静态方法的调用方式:

Singleton.singletonTest()

这种写法虽然看上去像是静态方法的调用,但其实 Kotlin 在背后自动帮我们创建了一个 Singleton 类的实例,并且保证全局只会存在一个 Singleton 实例。

2.6 Lambda 编程

2.6.0 什么是 Lambda 编程

Lambda 就是一小段可以作 为参数传递的代码,正常情况下,我们向某个方法传参时只能传入变量,必须经过一系列复杂的代码把这个参数得到,而借助Lambda却允许传入一小段代码,可以简化这个过程。

【MHH注解】可以将 Lambda 看成是一个没有方法名的方法!最后一行就相当于是 return 的参量。

2.6.1 集合的创建与遍历

集合的函数式 AP I是用来入门 Lambda 编程的绝佳示例,不过在此之前,我们得先学习创建集合 的方式才行。 传统意义上的集合主要就是 List 和 Set,再广泛一点的话,像 Map 这样的键值对数据结构也可 以包含进来。

List、Set 和 Map 在 Java 中都是接口,List 的主要实现类是 ArrayList 和 LinkedList,Set 的主要实现类是 HashSet,Map 的主要实现类是 HashMap,熟悉 Java 的人 对这些集合的实现类一定不会陌生。

现在我们提出一个需求,创建一个包含许多水果名称的集合。如果是在 Java 中你会怎么实现? 可能你首先会创建一个 ArrayList 的实例,然后将水果的名称一个个添加到集合中。当然,在 Kotlin中也可以这么做:

val list = ArrayList<String>()
list.add("Apple")
list.add("Banana")
list.add("Orange")
list.add("Pear")
list.add("Grape")

但是这种初始化集合的方式比较烦琐,为此 Kotlin 专门提供了一个内置的 listOf() 方法来简化 初始化集合的写法,如下所示:

val list = listOf("Apple", "Banana", "Orange", "Pear", "Grape")

可以看到,这里仅用一行代码就完成了集合的初始化操作。 还记得我们在学习循环语句时提到过的吗?for-in 循环不仅可以用来遍历区间,还可以用来遍 历集合。现在我们就尝试一下使用 for-in 循环来遍历这个水果集合,在 main() 函数中编写如下代码:

fun main() {
   
    val list = listOf("Apple", "Banana", "Orange", "Pear", "Grape")
    for (fruit in list) {
   
        println(fruit)
    }
}

不过需要注意的是,listOf() 方法创建的是一个不可变的集合。你也许不太能理解什么叫作不 可变的集合,因为在 Java 中这个概念不太常见。不可变的集合指的就是该集合只能用于读取, 我们无法对集合进行添加、修改或删除操作。 至于这么设计的理由,和 val 关键字、类默认不可继承的设计初衷是类似的,可见 Kotlin 在不可 变性方面控制得极其严格。那如果我们确实需要创建一个可变的集合呢?也很简单,使用 mutableListOf() 方法就可以了,示例如下:

fun main() {
   
    val list = mutableListOf("Apple", "Banana", "Orange", "Pear", "Grape")
    list.add("Watermelon")
    for (fruit in list) {
   
        println(fruit)
    }
}

前面我们介绍的都是 List 集合的用法,实际上 Set 集合的用法几乎与此一模一样,只是将创建 集合的方式换成了 setOf()mutableSetOf() 函数而已,这里就不再赘述啦!

需要注意,Set 集合中是不可以存放重复元素的,如果存放了多个相同的元素,只会保留其中一 份,这是和 List 集合最大的不同之处。当然这部分知识属于数据结构相关的内容,这里就不展 开讨论了。

最后再来看一下 Map 集合的用法。Map 是一种键值对形式的数据结构,因此在用法上和 List、 Set 集合有较大的不同。传统的 Map 用法是先创建一个 HashMap的实例,然后将一个个键值对数据添加到 Map 中。比如这里我们给每种水果设置一个对应的编号,就可以这样写:

val map = HashMap<String, Int>()
map.put("Apple", 1)
map.put("Banana", 2)
map.put("Orange", 3)
map.put("Pear", 4)
map.put("Grape", 5)

我之所以先用这种写法,是因为这种写法和Java语法是最相似的,因此可能最好理解。但其实 在 Kotlin 中并不建议使用 put()get() 方法来对 Map 进行添加和读取数据操作,而是更加推荐 使用一种类似于数组下标的语法结构,比如向 Map 中添加一条数据就可以这么写:

map["Apple"] = 1

而从Map中读取一条数据就可以这么写:

val number = map["Apple"]

因此,上述代码经过优化过后就可以变成如下形式:

val map = HashMap<String, Int>()
map["Apple"] = 1
map["Banana"] = 2
map["Orange"] = 3
map["Pear"] = 4
map["Grape"] = 5

当然,这仍然不是最简便的写法,因为 Kotlin 毫无疑问地提供了一对 mapOf()mutableMapOf() 函数来继续简化 Map 的用法。在 mapOf() 函数中,我们可以直接传入初始化 的键值对组合来完成对Map集合的创建:

val map = mapOf("Apple" to 1, "Banana" to 2, "Orange" to 3, "Pear" to 4, "Grape" to 5)

这里的键值对组合看上去好像是使用 to 这个关键字来进行关联的,但其实 to 并不是关键字,而 是一个 infix 函数,我们会在本书第 9 章的 Kotlin 课堂中深入探究 infix 函数的相关内容。

最后再来看一下如何遍历Map集合中的数据吧,其实使用的仍然是for-in循环。在main()函 数中编写如下代码:

fun main() {
   
    val map = mapOf("Apple" to 1, "Banana" to 2, "Orange" to 3, "Pear" to 4, "Grape" to 5)
    for ((fruit, number) in map) {
   
        println("fruit is " + fruit + ", number is " + number)
    }
}

这段代码主要的区别在于,在for-in循环中,我们将Map的键值对变量一起声明到了一对括号 里面,这样当进行循环遍历时,每次遍历的结果就会赋值给这两个键值对变量,最后将它们的值打印出来。

【注】python 中给 List 和 Dict 赋值直接 []、{}里面写就完事了,没有这么复杂,想念 python 的第 10086 h有感。

2.6.2 集合的函数式 API

首先来看一下 Lambda 的定义,如果用最直白的语言来阐述的话,Lambda就是一小段可以作 为参数传递的代码。

从定义上看,这个功能就很厉害了,因为正常情况下,我们向某个函数传 参时只能传入变量,而借助Lambda却允许传入一小段代码。我们来看一下Lambda表达式的语法结构:

{
   参数名1: 参数类型, 参数名2: 参数类型 -> 函数体}

这是 Lambda 表达式最完整的语法结构定义。

首先最外层是一对大括号,如果有参数传入到 Lambda 表达式中的话,我们还需要声明参数列表,参数列表的结尾使用一个 -> 符号,表示参数列表的结束以及函数体的开始,函数体中可以编写任意行代码(虽然不建议编写太长的代 码),并且最后一行代码会自动作为 Lambda 表达式的 返回值

当然,在很多情况下,我们并不需要使用 Lambda 表达式完整的语法结构,而是有很多种简化的写法。

找出最长单词水果的需求,使用的函数式 API 的语法结构看上去好像很特殊, 但其实 maxBy 就是一个普通的函数而已,只不过它接收的是一个 Lambda 类型的参数,并且会在遍历集合时将每次遍历的值作为参数传递给 Lambda 表达式。maxBy 函数的工作原理是根据我们传入的条件来遍历集合,从而找到该条件下的最大值,比如说想要找到单词最长的水果, 那么条件自然就应该是单词的长度了。

val list = listOf("Apple", "Banana", "Orange", "Pear", "Grape", "Watermelon")
val lambda = {
    fruit: String -> fruit.length }
val maxLengthFruit = list.maxBy(lambda)

可以看到,maxBy 函数实质上就是接收了一个 Lambda 参数而已,并且这个 Lambda 参数是完 全按照刚才学习的表达式的语法结构来定义的,因此这段代码应该算是比较好懂的。

这种写法虽然可以正常工作,但是比较啰嗦,可简化的点也非常多,下面我们就开始对这段代码一步步进行简化。

首先,我们不需要专门定义一个 lambda 变量,而是可以直接将 lambda 表达式传入 maxBy 函数 当中,因此第一步简化如下所示

你可能感兴趣的:(Android开发,android,kotlin,android,studio)