在这里插入图片描述

Android 开发期末速成重点知识总结

第1章 开始启程,你的第一行Android代码

重点知识

  • 应用软件:用户可使用的程序设计语言及应用程序的集合,分为应用软件包和用户程序。
  • 移动应用:面向个人(To C)或企业(To B),联网方式包括单机、局域网、互联网。
  • 常见操作系统:Windows、Linux(CentOS、Ubuntu)、ChromeOS、iOS/iPadOS、Android、HarmonyOS。
  • Android系统特点
    • 开放性(开源)
    • 平等性
    • 无界性
    • 硬件丰富
  • Android系统架构
    • Linux内核层:提供硬件驱动支持。
    • 系统运行库层:提供主要特性支持,如SQLite、OpenGL|ES、Webkit。
    • 应用框架层:提供构建应用程序的API。
    • 应用层:所有安装在手机上的应用程序。
  • Android主要系统版本:查看Android系统版本市占率
  • Android应用开发特色
    • 四大组件:Activity、Service、BroadcastReceiver、ContentProvider。
    • 丰富的系统控件。
    • SQLite数据库。
    • 强大的多媒体支持。
    • 支持机器学习模型部署。
  • 开发环境搭建
  • 创建HelloWorld项目
    • 选择Empty Views Activity。
    • 配置项目名称、包名、语言(Kotlin)、最低API级别。
  • 项目结构
    • app:代码和资源目录。
    • build.gradle:项目构建脚本。
    • settings.gradle:模块引入配置。
    • AndroidManifest.xml:应用配置文件。
  • 日志工具
    • Log.v():打印琐碎信息。
    • Log.d():打印调试信息。
    • Log.i():打印重要数据。
    • Log.w():打印警告信息。
    • Log.e():打印错误信息。

课后习题

单选题
  1. Android系统是基于以下哪种内核构建的?答案:B

    • A. Windows
    • B. Linux
    • C. macOS
    • D. ChromeOS
  2. Android应用开发中,以下哪种语言被推荐用于开发?答案:B

    • A. Java
    • B. Kotlin
    • C. Swift
    • D. Python
  3. 在Android Studio中创建项目时,以下哪个选项用于指定项目代码存放的位置?答案:C

    • A. Name
    • B. Package name
    • C. Save location
    • D. Language
  4. Android系统架构中,提供硬件驱动支持的是哪一层?答案:A

    • A. Linux内核层
    • B. 系统运行库层
    • C. 应用框架层
    • D. 应用层
  5. Android应用开发的四大组件不包括以下哪一项?答案:E

    • A. Activity
    • B. Service
    • C. BroadcastReceiver
    • D. ContentProvider
    • E. Fragment
  6. 在Android开发中,用于显示日志信息的方法是?答案:D

    • A. println()
    • B. print()
    • C. showLog()
    • D. Log.d()
  7. Android系统的主要特点是?答案:A

    • A. 开放性
    • B. 封闭性
    • C. 单一性
    • D. 专有性
  8. 在Android开发中,用于定义应用配置的文件是?答案:D

    • A. build.gradle
    • B. settings.gradle
    • C. AndroidManifest.xml
    • D. AndroidManifest.xml
  9. 在Android开发中,用于构建项目的文件是?答案:A

    • A. build.gradle
    • B. settings.gradle
    • C. AndroidManifest.xml
    • D. app
  10. 在Android开发中,用于管理模块引入的文件是?答案:B

    • A. build.gradle
    • B. settings.gradle
    • C. AndroidManifest.xml
    • D. app
  11. 在Android开发中,用于存储日志信息的方法是?答案:E

    • A. Log.v()
    • B. Log.d()
    • C. Log.i()
    • D. Log.w()
    • E. Log.e()
  12. 在Android开发中,用于显示错误信息的方法是?答案:E

    • A. Log.v()
    • B. Log.d()
    • C. Log.i()
    • D. Log.w()
    • E. Log.e()
  13. 在Android开发中,用于显示警告信息的方法是?答案:D

    • A. Log.v()
    • B. Log.d()
    • C. Log.i()
    • D. Log.w()
    • E. Log.e()
  14. 在Android开发中,用于显示重要信息的方法是?答案:C

    • A. Log.v()
    • B. Log.d()
    • C. Log.i()
    • D. Log.w()
    • E. Log.e()
  15. 在Android开发中,用于显示调试信息的方法是?答案:B

    • A. Log.v()
    • B. Log.d()
    • C. Log.i()
    • D. Log.w()
    • E. Log.e()
多选题
  1. Android系统架构包括以下哪些层次?答案:A, B, C, D

    • A. Linux内核层
    • B. 系统运行库层
    • C. 应用框架层
    • D. 应用层
    • E. 数据库层
  2. Android应用开发中,以下哪些是Android的四大组件?答案:A, B, C, D

    • A. Activity
    • B. Service
    • C. BroadcastReceiver
    • D. ContentProvider
    • E. Fragment
  3. 在Android开发中,以下哪些方法用于日志记录?答案:A, B, C, D, E

    • A. Log.v()
    • B. Log.d()
    • C. Log.i()
    • D. Log.w()
    • E. Log.e()
  4. 在Android开发中,以下哪些是常见的操作系统?答案:A, B, C, D, E

    • A. Windows
    • B. Linux
    • C. ChromeOS
    • D. iOS/iPadOS
    • E. Android
  5. 在Android开发中,以下哪些是Android应用开发的特色?答案:A, B, C, D

    • A. 四大组件
    • B. 丰富的系统控件
    • C. SQLite数据库
    • D. 强大的多媒体支持
    • E. 高性能计算
简答题
  1. 简述Android系统的开放性特点及其优势。

    • 答案:Android系统的开放性特点在于其开源性,允许开发者自由访问和修改源代码。这使得开发者可以定制系统功能,优化性能,增加新特性,从而提升用户体验。同时,开放性也促进了开发者社区的活跃,加速了技术的创新和发展。
  2. 请列举Android应用开发的四大组件,并简述它们的作用。

    • 答案
      • Activity:用于创建用户界面和处理用户交互。
      • Service:用于在后台执行长时间运行的任务,不提供用户界面。
      • BroadcastReceiver:用于监听和响应系统或应用发出的广播消息。
      • ContentProvider:用于跨应用共享数据,提供数据访问接口。
  3. 简述Android开发环境的搭建步骤。

    • 答案
      1. 下载并安装Android Studio。
      2. 配置SDK路径。
      3. 创建一个新的Android项目,选择项目类型、名称、包名、保存位置、语言和最低API级别。
      4. 点击“Finish”完成项目创建。
综合题
  1. 创建一个简单的Android项目,项目名称为MyFirstApp,包名为com.example.myfirstapp,保存位置为C:\AndroidProjects,使用Kotlin语言,最低API级别为API 21。请写出创建项目的步骤,并说明项目创建完成后,app目录下包含哪些主要文件及其作用。
    • 答案
      • 步骤
        1. 打开Android Studio,选择“Start a new Android Studio project”。
        2. 选择“Empty Activity”,点击“Next”。
        3. 在“Configure your new project”页面,填写项目名称MyFirstApp,包名com.example.myfirstapp,保存位置C:\AndroidProjects,选择语言Kotlin,最低API级别API 21
        4. 点击“Finish”完成项目创建。
      • app目录下主要文件及其作用
        • AndroidManifest.xml:定义应用的基本信息,包括活动、服务、广播接收器等组件的配置。
        • build.gradle:定义项目的构建配置,包括依赖项、插件等。
        • res目录:存储应用的资源,如布局文件、图片、字符串等。
        • src目录:存储应用的源代码,包括活动、服务等组件的实现。
        • assets目录:存储原始资源文件,如HTML、CSS、JavaScript等。
        • libs目录:存储应用的依赖库文件。

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

重点知识

  • Kotlin发展历程
    • 2011年发布第一个版本,2012年开源。
    • 2016年发布1.0正式版。
    • 2017年成为Android开发一级语言。
    • 2019年宣布Kotlin First。
  • Kotlin优势
    • 语法简洁,代码量少。
    • 语法高级,支持现代特性。
    • 语言安全,杜绝空指针异常。
    • 与Java完全兼容。
  • Kotlin工作原理
    • Kotlin代码编译成class文件,与Java虚拟机兼容。
  • 变量和函数
    • 变量
      • val:不可变变量。
      • var:可变变量。
    • 函数
      • 使用fun关键字定义。
      • 可以省略返回值类型。
      • 单行函数语法糖。
      • 示例:
        fun add(a: Int, b: Int): Int {
            return a + b
        }
        
        简化为:
        fun add(a: Int, b: Int) = a + b
        
  • 逻辑控制
    • if语句:可以有返回值。
      val max = if (a > b) a else b
      
    • when语句:替代if语句,支持多种匹配方式。
      when (x) {
          1 -> println("x == 1")
          2 -> println("x == 2")
          else -> println("x is neither 1 nor 2")
      }
      
    • for-in循环:遍历区间或集合。
      for (i in 1..10) {
          println(i)
      }
      
  • 面向对象编程
    • 类与对象
      class Person {
          var name: String = ""
          var age: Int = 0
          fun eat() {
              println("$name is eating. He is $age years old.")
          }
      }
      
    • 继承
      open class Person {
          var name: String = ""
          var age: Int = 0
      }
      class Student : Person() {
          var sno: String = ""
          var grade: Int = 0
      }
      
    • 接口
      interface Study {
          fun readBooks()
          fun doHomework()
      }
      
    • 数据类
      data class Cellphone(val brand: String, val price: Double)
      
    • 单例类
      object Singleton {
          fun singletonTest() {
              println("singletonTest is called.")
          }
      }
      
  • Lambda表达式
    • 一小段可以作为参数传递的代码。
    • 示例:
      val list = listOf("Apple", "Banana", "Orange")
      val newList = list.map { it.toUpperCase() }
      
  • 空指针检查
    • 可空类型系统Int?表示可为空的整型。
    • 判空辅助工具
      • ?.:安全调用。
      • ?::Elvis运算符。
      • let:延迟初始化。
      val a: String? = "Kotlin"
      val length = a?.length ?: 0
      

课后习题

单选题
  1. Kotlin语言是在哪一年发布的第一个版本?答案:A

    • A. 2011
    • B. 2012
    • C. 2016
    • D. 2017
  2. 在Kotlin中,val关键字用于声明什么类型的变量?答案:B

    • A. 可变变量
    • B. 不可变变量
    • C. 局部变量
    • D. 全局变量
  3. Kotlin中,fun关键字用于定义什么?答案:C

    • A. 类
    • B. 接口
    • C. 函数
    • D. 对象
  4. Kotlin中,when语句的作用是什么?答案:D

    • A. 循环
    • B. 条件判断
    • C. 数据转换
    • D. 多分支选择
  5. 在Kotlin中,var关键字用于声明什么类型的变量?答案:A

    • A. 可变变量
    • B. 不可变变量
    • C. 局部变量
    • D. 全局变量
  6. Kotlin中,fun关键字后面可以省略的是?答案:B

    • A. 参数列表
    • B. 返回值类型
    • C. 函数体
    • D. 函数名
  7. 在Kotlin中,when语句可以替代什么语句?答案:B

    • A. for
    • B. if
    • C. while
    • D. do...while
  8. 在Kotlin中,for-in循环用于遍历什么?答案:D

    • A. 数组
    • B. 集合
    • C. 字符串
    • D. 区间
  9. 在Kotlin中,valvar的区别是什么?答案:B

    • A. val用于声明局部变量,var用于声明全局变量
    • B. val用于声明不可变变量,var用于声明可变变量
    • C. val用于声明全局变量,var用于声明局部变量
    • D. val用于声明可变变量,var用于声明不可变变量
  10. 在Kotlin中,fun关键字后面可以省略的是?答案:B

    • A. 参数列表
    • B. 返回值类型
    • C. 函数体
    • D. 函数名
  11. 在Kotlin中,when语句可以替代什么语句?答案:B

    • A. for
    • B. if
    • C. while
    • D. do...while
  12. 在Kotlin中,for-in循环用于遍历什么?答案:D

    • A. 数组
    • B. 集合
    • C. 字符串
    • D. 区间
  13. 在Kotlin中,valvar的区别是什么?答案:B

    • A. val用于声明局部变量,var用于声明全局变量
    • B. val用于声明不可变变量,var用于声明可变变量
    • C. val用于声明全局变量,var用于声明局部变量
    • D. val用于声明可变变量,var用于声明不可变变量
  14. 在Kotlin中,fun关键字后面可以省略的是?答案:B

    • A. 参数列表
    • B. 返回值类型
    • C. 函数体
    • D. 函数名
  15. 在Kotlin中,when语句可以替代什么语句?答案:B

    • A. for
    • B. if
    • C. while
    • D. do...while
多选题
  1. Kotlin相比于Java的优势包括以下哪些?答案:A, B, C, D

    • A. 语法简洁
    • B. 语法高级
    • C. 语言安全
    • D. 与Java完全兼容
    • E. 更快的运行速度
  2. Kotlin中,以下哪些是逻辑控制语句?答案:A, B, C, D

    • A. if
    • B. when
    • C. for-in
    • D. while
    • E. switch
  3. 在Kotlin中,以下哪些是面向对象编程的特性?答案:A, B, C, D

    • A. 类与对象
    • B. 继承
    • C. 接口
    • D. 数据类
    • E. 单例类
  4. 在Kotlin中,以下哪些是空指针检查的工具?答案:A, B, C

    • A. ?.
    • B. ?:
    • C. let
    • D. also
    • E. apply
  5. 在Kotlin中,以下哪些是函数的特性?答案:A, B, C

    • A. 可以省略返回值类型
    • B. 可以使用单行函数语法糖
    • C. 可以作为参数传递
    • D. 必须显式声明返回值类型
    • E. 不能作为参数传递
简答题
  1. 简述Kotlin的单行函数语法糖及其作用。

    • 答案:Kotlin的单行函数语法糖允许将函数体直接写在=符号后面,省略return关键字。这种语法糖使代码更加简洁,适用于函数体只有一行代码的情况。
  2. 请写出Kotlin中定义一个类的语法,并说明类中可以包含哪些成员。

    • 答案
      • 定义类的语法
        class MyClass {
            var property: String = "Hello"
            fun myFunction() {
                println(property)
            }
        }
        
      • 类中可以包含的成员
        • 属性(Properties):用于存储数据。
        • 方法(Methods):用于定义行为。
        • 构造函数(Constructors):用于初始化对象。
        • 内部类(Inner Classes):定义在类内部的类。
        • 伴生对象(Companion Objects):用于定义静态成员。
  3. 请解释Kotlin中valvar的区别。

    • 答案val用于声明不可变变量,一旦赋值后不能更改;var用于声明可变变量,可以多次赋值。
综合题
  1. 创建一个Kotlin类Student,包含以下属性和方法:
    • 属性:
      • name:学生姓名(不可变变量)
      • age:学生年龄(可变变量)
    • 方法:
      • study():打印“name is studying. He/She is age years old.”
      • takeExam():打印“name is taking an exam.”
    • 请写出完整的类定义代码,并创建一个Student对象,调用其方法。
    • 答案
      class Student(val name: String, var age: Int) {
          fun study() {
              println("$name is studying. He/She is $age years old.")
          }
      
          fun takeExam() {
              println("$name is taking an exam.")
          }
      }
      
      fun main() {
          val student = Student("Alice", 20)
          student.study()
          student.age = 21
          student.takeExam()
      }
      

好的,以下是第3章的内容,按照调整后的格式进行整理:


第3章 先从看得到的入手,探究Activity

重点知识

  • Activity:包含用户界面的组件,用于与用户交互。
  • Activity基本用法
    • 手动创建Activity:通过Android Studio创建Empty Views Activity。
    • 配置AndroidManifest.xml:注册Activity。
    • 加载布局:使用setContentView()方法。
  • Toast:用于显示短消息。
    • 示例:
      Toast.makeText(this, "Hello, World!", Toast.LENGTH_SHORT).show()
      
  • Menu:用于创建菜单。
    • 示例:
      override fun onCreateOptionsMenu(menu: Menu?): Boolean {
          menuInflater.inflate(R.menu.main, menu)
          return true
      }
      
  • Intent:用于组件间通信。
    • 显式Intent:指定目标组件。
      val intent = Intent(this, SecondActivity::class.java)
      startActivity(intent)
      
    • 隐式Intent:通过action和category指定目标组件。
      val intent = Intent(Intent.ACTION_VIEW)
      intent.data = Uri.parse("https://www.example.com")
      startActivity(intent)
      
  • Activity的生命周期
    • onCreate():创建时调用。
    • onStart():从不可见到可见时调用。
    • onResume():准备与用户交互时调用。
    • onPause():准备启动或恢复其他Activity时调用。
    • onStop():完全不可见时调用。
    • onDestroy():销毁前调用。
    • onRestart():从停止状态重新启动时调用。
  • Activity的启动模式
    • standard:每次启动都创建新实例。
    • singleTop:栈顶已存在实例则复用。
    • singleTask:检查栈中实例,存在则复用并清空其上所有Activity。
    • singleInstance:独立栈,全局唯一实例。
  • ViewBinding
    • 替代findViewById,更安全、更方便。
    • 示例:
      private lateinit var binding: ActivityMainBinding
      override fun onCreate(savedInstanceState: Bundle?) {
          super.onCreate(savedInstanceState)
          binding = ActivityMainBinding.inflate(layoutInflater)
          setContentView(binding.root)
      }
      

课后习题

单选题
  1. Activity是Android中的一个重要组件,主要用于:答案:B

    • A. 后台服务
    • B. 用户界面交互
    • C. 数据存储
    • D. 网络通信
  2. 在Android中,Toast的作用是:答案:B

    • A. 显示长时间的提示信息
    • B. 显示短时间的提示信息
    • C. 弹出一个对话框
    • D. 显示一个菜单
  3. Intent在Android中主要用于:答案:B

    • A. 数据存储
    • B. 组件间通信
    • C. 网络请求
    • D. 用户界面绘制
  4. 在Android中,Activity的生命周期方法onCreate()的作用是:答案:A

    • A. 创建时调用
    • B. 从不可见到可见时调用
    • C. 准备与用户交互时调用
    • D. 准备启动或恢复其他Activity时调用
  5. 在Android中,Activity的生命周期方法onResume()的作用是:答案:C

    • A. 创建时调用
    • B. 从不可见到可见时调用
    • C. 准备与用户交互时调用
    • D. 准备启动或恢复其他Activity时调用
  6. 在Android中,Activity的生命周期方法onPause()的作用是:答案:D

    • A. 创建时调用
    • B. 从不可见到可见时调用
    • C. 准备与用户交互时调用
    • D. 准备启动或恢复其他Activity时调用
  7. 在Android中,Activity的生命周期方法onStop()的作用是:答案:B

    • A. 创建时调用
    • B. 完全不可见时调用
    • C. 准备与用户交互时调用
    • D. 准备启动或恢复其他Activity时调用
  8. 在Android中,Activity的生命周期方法onDestroy()的作用是:答案:B

    • A. 创建时调用
    • B. 销毁前调用
    • C. 准备与用户交互时调用
    • D. 准备启动或恢复其他Activity时调用
  9. 在Android中,Activity的生命周期方法onRestart()的作用是:答案:A

    • A. 从停止状态重新启动时调用
    • B. 从不可见到可见时调用
    • C. 准备与用户交互时调用
    • D. 准备启动或恢复其他Activity时调用
  10. 在Android中,Activity的启动模式standard的特点是:答案:A

    • A. 每次启动都创建新实例
    • B. 栈顶已存在实例则复用
    • C. 检查栈中实例,存在则复用并清空其上所有Activity
    • D. 独立栈,全局唯一实例
  11. 在Android中,Activity的启动模式singleTop的特点是:答案:B

    • A. 每次启动都创建新实例
    • B. 栈顶已存在实例则复用
    • C. 检查栈中实例,存在则复用并清空其上所有Activity
    • D. 独立栈,全局唯一实例
  12. 在Android中,Activity的启动模式singleTask的特点是:答案:C

    • A. 每次启动都创建新实例
    • B. 栈顶已存在实例则复用
    • C. 检查栈中实例,存在则复用并清空其上所有Activity
    • D. 独立栈,全局唯一实例
  13. 在Android中,Activity的启动模式singleInstance的特点是:答案:D

    • A. 每次启动都创建新实例
    • B. 栈顶已存在实例则复用
    • C. 检查栈中实例,存在则复用并清空其上所有Activity
    • D. 独立栈,全局唯一实例
  14. 在Android中,ViewBinding的作用是:答案:A

    • A. 替代findViewById,更安全、更方便
    • B. 用于创建后台服务
    • C. 用于网络请求
    • D. 用于数据存储
  15. 在Android中,Toast的显示时间Toast.LENGTH_SHORT表示:答案:B

    • A. 长时间显示
    • B. 短时间显示
    • C. 永久显示
    • D. 不显示
多选题
  1. Activity的生命周期中,以下哪些方法是在Activity可见时调用的?答案:B, C

    • A. onCreate()
    • B. onStart()
    • C. onResume()
    • D. onPause()
  2. Activity的启动模式包括以下哪些?答案:A, B, C, D

    • A. standard
    • B. singleTop
    • C. singleTask
    • D. singleInstance
  3. 在Android中,以下哪些是Intent的用途?答案:A, B, C

    • A. 启动Activity
    • B. 启动Service
    • C. 发送广播
    • D. 创建线程
  4. 在Android中,以下哪些是Activity的生命周期方法?答案:A, B, C, D, E, F

    • A. onCreate()
    • B. onStart()
    • C. onResume()
    • D. onPause()
    • E. onStop()
    • F. onDestroy()
  5. 在Android中,以下哪些是Toast的特点?答案:A, B

    • A. 显示短时间的提示信息
    • B. 不需要用户交互
    • C. 可以显示长时间的提示信息
    • D. 需要用户交互
简答题
  1. 简述Activity的生命周期,并说明每个生命周期方法的作用。

    • 答案
      • onCreate():Activity创建时调用,用于初始化资源。
      • onStart():Activity从不可见到可见时调用。
      • onResume():Activity准备与用户交互时调用。
      • onPause():系统准备启动或恢复另一个Activity时调用。
      • onStop():Activity完全不可见时调用。
      • onDestroy():Activity销毁前调用。
      • onRestart():Activity从停止状态重新启动时调用。
  2. 请解释Intent的作用,并给出显式Intent和隐式Intent的区别。

    • 答案
      • Intent用于组件间通信,包括启动Activity、Service和发送Broadcast。
      • 显式Intent:明确指定目标组件的名称,通常用于内部组件间的通信。
      • 隐式Intent:通过action和category等信息指定目标组件,通常用于跨应用通信。
  3. 简述Activity的启动模式及其特点。

    • 答案
      • standard:每次启动都创建新实例。
      • singleTop:栈顶已存在实例则复用。
      • singleTask:检查栈中实例,存在则复用并清空其上所有Activity。
      • singleInstance:独立栈,全局唯一实例。
综合题
  1. 创建一个名为FirstActivity的Activity,并在其中添加一个按钮。当点击按钮时,使用显式Intent跳转到SecondActivity。请写出FirstActivitySecondActivity的代码,以及AndroidManifest.xml中的注册代码。
    • 答案
      • FirstActivity代码
        class FirstActivity : AppCompatActivity() {
            override fun onCreate(savedInstanceState: Bundle?) {
                super.onCreate(savedInstanceState)
                setContentView(R.layout.activity_first)
        
                val button: Button = findViewById(R.id.button)
                button.setOnClickListener {
                    val intent = Intent(this, SecondActivity::class.java)
                    startActivity(intent)
                }
            }
        }
        
      • SecondActivity代码
        class SecondActivity : AppCompatActivity() {
            override fun onCreate(savedInstanceState: Bundle?) {
                super.onCreate(savedInstanceState)
                setContentView(R.layout.activity_second)
            }
        }
        
      • AndroidManifest.xml注册代码
        <application
            ...>
            <activity android:name=".FirstActivity">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
            <activity android:name=".SecondActivity" />
        </application>
        

以上是第3章的内容,后续章节将按照同样的格式进行整理。

好的,以下是第4章的内容,按照调整后的格式进行整理:


第4章 软件也要拼脸蛋,UI开发的点点滴滴

重点知识

  • 常用控件

    • TextView:用于显示文本信息。
      <TextView
          android:id="@+id/textView"
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
          android:text="Hello, World!" />
      
    • Button:用于用户交互。
      <Button
          android:id="@+id/button"
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
          android:text="Click Me" />
      
    • EditText:用于输入文本。
      <EditText
          android:id="@+id/editText"
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
          android:hint="Enter text here" />
      
    • ImageView:用于显示图片。
      <ImageView
          android:id="@+id/imageView"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:src="@drawable/image" />
      
    • ProgressBar:用于显示进度。
      <ProgressBar
          android:id="@+id/progressBar"
          android:layout_width="match_parent"
          android:layout_height="wrap_content" />
      
    • AlertDialog:用于显示对话框。
      AlertDialog.Builder(this).apply {
          setTitle("Title")
          setMessage("Message")
          setPositiveButton("OK") { dialog, which -> }
          setNegativeButton("Cancel") { dialog, which -> }
          show()
      }
      
  • 布局

    • LinearLayout:线性布局,控件按顺序排列。
      <LinearLayout
          android:orientation="vertical"
          android:layout_width="match_parent"
          android:layout_height="match_parent">
          <Button android:text="Button 1" ... />
          <Button android:text="Button 2" ... />
      </LinearLayout>
      
    • RelativeLayout:相对布局,控件相对位置。
      <RelativeLayout
          android:layout_width="match_parent"
          android:layout_height="match_parent">
          <Button
              android:id="@+id/button1"
              android:layout_alignParentTop="true"
              android:text="Button 1" ... />
          <Button
              android:layout_below="@id/button1"
              android:text="Button 2" ... />
      </RelativeLayout>
      
    • FrameLayout:帧布局,控件堆叠。
      <FrameLayout
          android:layout_width="match_parent"
          android:layout_height="match_parent">
          <TextView android:text="Text" ... />
          <Button android:text="Button" ... />
      </FrameLayout>
      
  • RecyclerView

    • 基本步骤
      1. 添加依赖库。
      2. 在布局文件中添加RecyclerView
      3. 定义实体类和子项布局。
      4. 创建AdapterViewHolder
      5. 设置LayoutManagerAdapter
    • 示例代码
      class FruitAdapter(val fruitList: List<Fruit>) : RecyclerView.Adapter<FruitAdapter.ViewHolder>() {
          inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
              val fruitImage: ImageView = view.findViewById(R.id.fruitImage)
              val fruitName: TextView = view.findViewById(R.id.fruitName)
          }
      
          override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
              val view = LayoutInflater.from(parent.context).inflate(R.layout.fruit_item, parent, false)
              return ViewHolder(view)
          }
      
          override fun onBindViewHolder(holder: ViewHolder, position: Int) {
              val fruit = fruitList[position]
              holder.fruitImage.setImageResource(fruit.imageId)
              holder.fruitName.text = fruit.name
          }
      
          override fun getItemCount() = fruitList.size
      }
      

课后习题

单选题
  1. 在Android中,TextView用于:答案:B

    • A. 显示图片
    • B. 显示文本
    • C. 按钮点击
    • D. 输入文本
  2. RecyclerView的主要优点是:答案:C

    • A. 支持多种布局
    • B. 数据自动刷新
    • C. 高效的视图复用
    • D. 简单的布局管理
  3. LinearLayoutorientation属性可以设置为:答案:A, B

    • A. horizontal
    • B. vertical
    • C. both
    • D. none
  4. 在Android中,Button的作用是:答案:B

    • A. 显示文本
    • B. 用户交互
    • C. 输入文本
    • D. 显示图片
  5. 在Android中,EditText的作用是:答案:D

    • A. 显示文本
    • B. 用户交互
    • C. 显示图片
    • D. 输入文本
  6. 在Android中,ImageView的作用是:答案:D

    • A. 显示文本
    • B. 用户交互
    • C. 输入文本
    • D. 显示图片
  7. 在Android中,ProgressBar的作用是:答案:B

    • A. 显示文本
    • B. 显示进度
    • C. 输入文本
    • D. 显示图片
  8. 在Android中,AlertDialog的作用是:答案:B

    • A. 显示文本
    • B. 显示对话框
    • C. 输入文本
    • D. 显示图片
  9. 在Android中,LinearLayoutorientation属性默认值是:答案:B

    • A. horizontal
    • B. vertical
    • C. both
    • D. none
  10. 在Android中,RelativeLayout的特点是:答案:C

    • A. 控件按顺序排列
    • B. 控件堆叠
    • C. 控件相对位置
    • D. 控件网格排列
  11. 在Android中,FrameLayout的特点是:答案:B

    • A. 控件按顺序排列
    • B. 控件堆叠
    • C. 控件相对位置
    • D. 控件网格排列
  12. 在Android中,RecyclerViewAdapter的作用是:答案:C

    • A. 管理布局
    • B. 提供数据
    • C. 绑定数据到视图
    • D. 管理线程
  13. 在Android中,RecyclerViewViewHolder的作用是:答案:B

    • A. 管理布局
    • B. 缓存视图
    • C. 绑定数据到视图
    • D. 管理线程
  14. 在Android中,RecyclerViewLayoutManager的作用是:答案:A

    • A. 管理布局
    • B. 提供数据
    • C. 绑定数据到视图
    • D. 管理线程
  15. 在Android中,RecyclerViewAdapter必须实现的方法是:答案:D

    • A. onCreateViewHolder()
    • B. onBindViewHolder()
    • C. getItemCount()
    • D. 所有以上选项
多选题
  1. 以下哪些是Android中的常用控件?答案:A, B, C, D

    • A. TextView
    • B. Button
    • C. EditText
    • D. ImageView
  2. RecyclerView的使用步骤包括以下哪些?答案:A, B, C, D

    • A. 添加依赖库
    • B. 定义实体类和子项布局
    • C. 创建AdapterViewHolder
    • D. 设置LayoutManagerAdapter
  3. 在Android中,以下哪些是布局类型?答案:A, B, C

    • A. LinearLayout
    • B. RelativeLayout
    • C. FrameLayout
    • D. RecyclerView
  4. 在Android中,以下哪些是RecyclerView的特性?答案:A, B, C

    • A. 高效的视图复用
    • B. 支持多种布局
    • C. 数据绑定
    • D. 自动刷新
  5. 在Android中,以下哪些是AlertDialog的常用方法?答案:A, B, C

    • A. setTitle()
    • B. setMessage()
    • C. setPositiveButton()
    • D. setNegativeButton()
简答题
  1. 简述LinearLayoutRelativeLayout的区别。

    • 答案
      • LinearLayout:线性布局,控件按顺序排列,支持水平或垂直方向。
      • RelativeLayout:相对布局,控件相对位置,可以指定控件相对于父布局或其他控件的位置。
  2. 请解释RecyclerView的工作原理。

    • 答案
      • RecyclerView通过AdapterViewHolder模式高效地复用视图。
      • Adapter负责提供数据和视图绑定逻辑。
      • ViewHolder用于缓存视图,减少findViewById的调用,提高性能。
      • LayoutManager负责管理布局,支持多种布局方式(如线性、网格等)。
  3. 简述RecyclerViewAdapterViewHolderLayoutManager的作用。

    • 答案
      • Adapter:负责提供数据和视图绑定逻辑。
      • ViewHolder:用于缓存视图,减少findViewById的调用,提高性能。
      • LayoutManager:负责管理布局,支持多种布局方式(如线性、网格等)。
综合题
  1. 创建一个名为MainActivity的Activity,并在其中使用RecyclerView显示一个水果列表。水果列表包含水果名称和图片。请写出MainActivity的代码,以及RecyclerView的适配器代码和布局文件。
    • 答案
      • MainActivity代码
        class MainActivity : AppCompatActivity() {
            private val fruitList = listOf(
                Fruit("Apple", R.drawable.apple_pic),
                Fruit("Banana", R.drawable.banana_pic),
                Fruit("Orange", R.drawable.orange_pic)
            )
        
            override fun onCreate(savedInstanceState: Bundle?) {
                super.onCreate(savedInstanceState)
                setContentView(R.layout.activity_main)
        
                val recyclerView: RecyclerView = findViewById(R.id.recyclerView)
                val layoutManager = LinearLayoutManager(this)
                recyclerView.layoutManager = layoutManager
                val adapter = FruitAdapter(fruitList)
                recyclerView.adapter = adapter
            }
        }
        
      • FruitAdapter代码
        class FruitAdapter(val fruitList: List<Fruit>) : RecyclerView.Adapter<FruitAdapter.ViewHolder>() {
            inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
                val fruitImage: ImageView = view.findViewById(R.id.fruitImage)
                val fruitName: TextView = view.findViewById(R.id.fruitName)
            }
        
            override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
                val view = LayoutInflater.from(parent.context).inflate(R.layout.fruit_item, parent, false)
                return ViewHolder(view)
            }
        
            override fun onBindViewHolder(holder: ViewHolder, position: Int) {
                val fruit = fruitList[position]
                holder.fruitImage.setImageResource(fruit.imageId)
                holder.fruitName.text = fruit.name
            }
        
            override fun getItemCount() = fruitList.size
        }
        
      • fruit_item布局文件
        <LinearLayout
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:padding="8dp">
        
            <ImageView
                android:id="@+id/fruitImage"
                android:layout_width="40dp"
                android:layout_height="40dp"
                android:src="@drawable/ic_launcher_background" />
        
            <TextView
                android:id="@+id/fruitName"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_vertical"
                android:layout_marginStart="16dp"
                android:text="Fruit Name"
                android:textSize="16sp" />
        </LinearLayout>
        
      • activity_main布局文件
        <LinearLayout
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">
        
            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/recyclerView"
                android:layout_width="match_parent"
                android:layout_height="match_parent" />
        </LinearLayout>
        

第5章 手机平板要兼顾,探究Fragment

重点知识

  • Fragment:嵌入在Activity中的UI片段,用于合理利用大屏幕空间。
  • Fragment基本用法
    • 定义Fragment的布局文件。
    • 创建Fragment类,重写onCreateView()方法。
    • 在Activity布局中使用<fragment>标签引入Fragment。
  • 动态添加Fragment
    • 使用FragmentManagerFragmentTransaction动态添加或替换Fragment。
    • 示例:
      val fragmentManager = supportFragmentManager
      val transaction = fragmentManager.beginTransaction()
      transaction.replace(R.id.fragment_container, MyFragment())
      transaction.commit()
      
  • Fragment生命周期
    • onAttach():Fragment与Activity关联时调用。
    • onCreateView():创建视图时调用。
    • onActivityCreated():Activity创建完成后调用。
    • onDestroyView():视图销毁时调用。
    • onDetach():Fragment与Activity解除关联时调用。
添加一个Fragment
onAttach
onCreate
onCreateView
onActivityCreated
onStart
onResume
Fragment已激活
用户点击返回键或Fragment被移除/替换
onPause
onStop
onDestroyView
onDestroy
onDetach
Fragment被销毁
从返回栈中回到上一个Fragment
  • 限定符
    • large:用于大屏幕设备。
    • smallest-width:根据最小宽度加载布局。
    • 示例:
      res/layout-large/activity_main.xml
      res/layout-sw600dp/activity_main.xml
      

课后习题

单选题
  1. Fragment主要用于:答案:B

    • A. 后台服务
    • B. 用户界面片段
    • C. 数据存储
    • D. 网络通信
  2. 在Android中,动态添加Fragment时,使用以下哪个类进行管理?答案:A

    • A. FragmentManager
    • B. FragmentTransaction
    • C. FragmentActivity
    • D. Fragment
  3. Fragment的生命周期中,onAttach()方法的作用是:答案:B

    • A. 创建视图
    • B. Fragment与Activity关联时调用
    • C. 销毁视图
    • D. 解除与Activity的关联
  4. 在Android中,FragmentonCreateView()方法返回的是:答案:B

    • A. Fragment
    • B. View
    • C. Activity
    • D. Context
  5. 在Android中,FragmentonActivityCreated()方法的作用是:答案:C

    • A. 创建视图
    • B. Fragment与Activity关联时调用
    • C. Activity创建完成后调用
    • D. 销毁视图
  6. 在Android中,FragmentonDestroyView()方法的作用是:答案:C

    • A. 创建视图
    • B. Fragment与Activity关联时调用
    • C. 视图销毁时调用
    • D. 解除与Activity的关联
  7. 在Android中,FragmentonDetach()方法的作用是:答案:D

    • A. 创建视图
    • B. Fragment与Activity关联时调用
    • C. 销毁视图
    • D. 解除与Activity的关联
  8. 在Android中,FragmentonAttach()方法的参数是:答案:C

    • A. Fragment
    • B. View
    • C. Context
    • D. Activity
  9. 在Android中,FragmentonCreateView()方法的参数不包括:答案:D

    • A. inflater: LayoutInflater
    • B. container: ViewGroup?
    • C. savedInstanceState: Bundle?
    • D. context: Context
  10. 在Android中,FragmentonActivityCreated()方法的参数是:答案:C

    • A. Fragment
    • B. View
    • C. Bundle?
    • D. Context
  11. 在Android中,FragmentonDestroyView()方法的参数是:答案:None

    • A. Fragment
    • B. View
    • C. Bundle?
    • D. Context
  12. 在Android中,FragmentonDetach()方法的参数是:答案:None

    • A. Fragment
    • B. View
    • C. Bundle?
    • D. Context
  13. 在Android中,FragmentonCreateView()方法中,inflater的作用是:答案:A

    • A. 用于布局文件的解析
    • B. 用于创建视图
    • C. 用于保存实例状态
    • D. 用于销毁视图
  14. 在Android中,FragmentonActivityCreated()方法中,savedInstanceState的作用是:答案:C

    • A. 用于创建视图
    • B. 用于销毁视图
    • C. 用于保存实例状态
    • D. 用于关联Activity
  15. 在Android中,FragmentonDestroyView()方法中,view的作用是:答案:None

    • A. 用于创建视图
    • B. 用于销毁视图
    • C. 用于保存实例状态
    • D. 用于关联Activity
多选题
  1. Fragment的生命周期方法包括以下哪些?答案:A, B, C, D, E

    • A. onAttach()
    • B. onCreateView()
    • C. onActivityCreated()
    • D. onDestroyView()
    • E. onDetach()
  2. Fragment的使用场景包括以下哪些?答案:A, B, C

    • A. 在平板上合理利用大屏幕空间
    • B. 动态添加或替换UI片段
    • C. 实现复杂的布局结构
    • D. 替代Activity
  3. 在Android中,以下哪些是Fragment的生命周期方法?答案:A, B, C, D, E

    • A. onAttach()
    • B. onCreateView()
    • C. onActivityCreated()
    • D. onDestroyView()
    • E. onDetach()
  4. 在Android中,以下哪些是Fragment的特性?答案:A, B, C

    • A. 可以嵌入在Activity中
    • B. 可以动态添加或替换
    • C. 可以保存实例状态
    • D. 可以替代Activity
  5. 在Android中,以下哪些是Fragment的生命周期回调方法?答案:A, B, C, D, E

    • A. onAttach()
    • B. onCreateView()
    • C. onActivityCreated()
    • D. onDestroyView()
    • E. onDetach()
简答题
  1. 简述Fragment与Activity的关系。

    • 答案
      • Fragment嵌入在Activity中,依赖于Activity的生命周期。
      • Activity可以包含多个Fragment,Fragment可以动态添加、替换或移除。
  2. 请解释Fragment的生命周期方法onCreateView()onActivityCreated()的区别。

    • 答案
      • onCreateView():创建Fragment的视图时调用,返回Fragment的根视图。
      • onActivityCreated():Activity创建完成后调用,用于初始化Fragment的其他组件。
  3. 简述Fragment的生命周期。

    • 答案
      • onAttach():Fragment与Activity关联时调用。
      • onCreateView():创建视图时调用。
      • onActivityCreated():Activity创建完成后调用。
      • onDestroyView():视图销毁时调用。
      • onDetach():Fragment与Activity解除关联时调用。
综合题
  1. 创建一个名为MainActivity的Activity,并在其中动态添加两个Fragment:LeftFragmentRightFragmentLeftFragment包含一个按钮,点击按钮时动态替换RightFragmentAnotherRightFragment。请写出MainActivityLeftFragmentRightFragmentAnotherRightFragment的代码,以及AndroidManifest.xml中的注册代码。
    • 答案
      • MainActivity代码
        class MainActivity : AppCompatActivity() {
            override fun onCreate(savedInstanceState: Bundle?) {
                super.onCreate(savedInstanceState)
                setContentView(R.layout.activity_main)
        
                if (savedInstanceState == null) {
                    supportFragmentManager.beginTransaction()
                        .add(R.id.left_fragment_container, LeftFragment())
                        .add(R.id.right_fragment_container, RightFragment())
                        .commit()
                }
            }
        }
        
      • LeftFragment代码
        class LeftFragment : Fragment() {
            override fun onCreateView(
                inflater: LayoutInflater, container: ViewGroup?,
                savedInstanceState: Bundle?
            ): View? {
                val view = inflater.inflate(R.layout.fragment_left, container, false)
                val button: Button = view.findViewById(R.id.button)
                button.setOnClickListener {
                    val fragmentManager = parentFragmentManager
                    val transaction = fragmentManager.beginTransaction()
                    transaction.replace(R.id.right_fragment_container, AnotherRightFragment())
                    transaction.commit()
                }
                return view
            }
        }
        
      • RightFragment代码
        class RightFragment : Fragment() {
            override fun onCreateView(
                inflater: LayoutInflater, container: ViewGroup?,
                savedInstanceState: Bundle?
            ): View? {
                return inflater.inflate(R.layout.fragment_right, container, false)
            }
        }
        
      • AnotherRightFragment代码
        class AnotherRightFragment : Fragment() {
            override fun onCreateView(
                inflater: LayoutInflater, container: ViewGroup?,
                savedInstanceState: Bundle?
            ): View? {
                return inflater.inflate(R.layout.fragment_another_right, container, false)
            }
        }
        
      • activity_main布局文件
        <LinearLayout
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="horizontal">
        
            <FrameLayout
                android:id="@+id/left_fragment_container"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1" />
        
            <FrameLayout
                android:id="@+id/right_fragment_container"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1" />
        </LinearLayout>
        
      • fragment_left布局文件
        <LinearLayout
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"
            android:gravity="center">
        
            <Button
                android:id="@+id/button"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Replace Fragment" />
        </LinearLayout>
        
      • fragment_right布局文件
        <LinearLayout
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"
            android:gravity="center">
        
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Right Fragment" />
        </LinearLayout>
        
      • fragment_another_right布局文件
        <LinearLayout
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"
            android:gravity="center">
        
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Another Right Fragment" />
        </LinearLayout>
        
      • AndroidManifest.xml注册代码
        <application
            ...>
            <activity android:name=".MainActivity">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
        </application>
        

第6章 全局大喇叭,详解广播机制

重点知识

  • 广播机制:Android提供的一种组件间通信机制。
  • 广播分类
    • 标准广播:异步执行,无先后顺序。
    • 有序广播:同步执行,有先后顺序,可被截断。
  • 注册广播接收器
    • 动态注册:在代码中注册,需在onDestroy()中注销。
      val intentFilter = IntentFilter("android.intent.action.TIME_TICK")
      val receiver = TimeChangeReceiver()
      registerReceiver(receiver, intentFilter)
      
    • 静态注册:在AndroidManifest.xml中注册。
      <receiver android:name=".BootCompleteReceiver">
          <intent-filter>
              <action android:name="android.intent.action.BOOT_COMPLETED" />
          </intent-filter>
      </receiver>
      
  • 发送广播
    • 标准广播
      val intent = Intent("com.example.MY_BROADCAST")
      sendBroadcast(intent)
      
    • 有序广播
      val intent = Intent("com.example.MY_BROADCAST")
      sendOrderedBroadcast(intent, null)
      
  • 广播优先级
    • AndroidManifest.xml中通过android:priority设置。
    • 动态注册通过IntentFilter设置。
  • 广播截断
    • onReceive()中调用abortBroadcast()
  • 运行时权限
    • 需在AndroidManifest.xml中声明权限。
    • 示例:
      <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
      

课后习题

单选题
  1. 在Android中,标准广播的特点是:答案:D

    • A. 同步执行
    • B. 有先后顺序
    • C. 可被截断
    • D. 异步执行
  2. 动态注册的广播接收器需要在何时注销?答案:C

    • A. onCreate()
    • B. onStart()
    • C. onDestroy()
    • D. onPause()
  3. 在Android中,发送有序广播的方法是:答案:B

    • A. sendBroadcast()
    • B. sendOrderedBroadcast()
    • C. sendStickyBroadcast()
    • D. sendBroadcastAsUser()
  4. 在Android中,广播接收器的onReceive()方法中,调用哪个方法可以截断广播?答案:A

    • A. abortBroadcast()
    • B. stopBroadcast()
    • C. cancelBroadcast()
    • D. endBroadcast()
  5. 在Android中,IntentFilter的作用是:答案:B

    • A. 发送广播
    • B. 过滤广播
    • C. 注册广播
    • D. 接收广播
  6. 在Android中,BroadcastReceiveronReceive()方法的参数是:答案:B

    • A. ContextIntent
    • B. ContextIntent
    • C. IntentBundle
    • D. ContextBundle
  7. 在Android中,BroadcastReceiveronReceive()方法中,Intent的作用是:答案:A

    • A. 携带广播数据
    • B. 注册广播
    • C. 发送广播
    • D. 接收广播
  8. 在Android中,BroadcastReceiveronReceive()方法中,Context的作用是:答案:C

    • A. 发送广播
    • B. 注册广播
    • C. 提供上下文环境
    • D. 接收广播
  9. 在Android中,BroadcastReceiveronReceive()方法中,abortBroadcast()的作用是:答案:A

    • A. 截断广播
    • B. 停止广播
    • C. 取消广播
    • D. 结束广播
  10. 在Android中,BroadcastReceiveronReceive()方法中,IntentFilter的作用是:答案:B

    • A. 发送广播
    • B. 过滤广播
    • C. 注册广播
    • D. 接收广播
  11. 在Android中,BroadcastReceiveronReceive()方法中,Context的作用是:答案:C

    • A. 发送广播
    • B. 注册广播
    • C. 提供上下文环境
    • D. 接收广播
  12. 在Android中,BroadcastReceiveronReceive()方法中,Intent的作用是:答案:A

    • A. 携带广播数据
    • B. 注册广播
    • C. 发送广播
    • D. 接收广播
  13. 在Android中,BroadcastReceiveronReceive()方法中,abortBroadcast()的作用是:答案:A

    • A. 截断广播
    • B. 停止广播
    • C. 取消广播
    • D. 结束广播
  14. 在Android中,BroadcastReceiveronReceive()方法中,IntentFilter的作用是:答案:B

    • A. 发送广播
    • B. 过滤广播
    • C. 注册广播
    • D. 接收广播
  15. 在Android中,BroadcastReceiveronReceive()方法中,Context的作用是:答案:C

    • A. 发送广播
    • B. 注册广播
    • C. 提供上下文环境
    • D. 接收广播
多选题
  1. 广播的分类包括以下哪些?答案:A, B

    • A. 标准广播
    • B. 有序广播
    • C. 系统广播
    • D. 自定义广播
  2. 广播接收器的注册方式包括以下哪些?答案:A, B

    • A. 动态注册
    • B. 静态注册
    • C. 临时注册
    • D. 永久注册
  3. 在Android中,以下哪些是广播接收器的生命周期方法?答案:A

    • A. onReceive()
    • B. onCreate()
    • C. onStart()
    • D. onDestroy()
  4. 在Android中,以下哪些是广播的特性?答案:A, B, C

    • A. 可以异步执行
    • B. 可以同步执行
    • C. 可以被截断
    • D. 可以替代Activity
  5. 在Android中,以下哪些是广播的用途?答案:A, B, C

    • A. 组件间通信
    • B. 监听系统事件
    • C. 应用间通信
    • D. 替代Service
简答题
  1. 简述广播接收器的生命周期。

    • 答案
      • 广播接收器的生命周期较短,主要方法是onReceive()
      • onReceive():接收广播时调用,用于处理广播事件。
  2. 请解释有序广播的特点。

    • 答案
      • 有序广播是同步执行的。
      • 广播接收器有先后顺序,优先级高的先接收。
      • 前一个接收器可以截断广播,阻止后续接收器接收。
  3. 简述广播的分类及其特点。

    • 答案
      • 标准广播:异步执行,无先后顺序。
      • 有序广播:同步执行,有先后顺序,可被截断。
综合题
  1. 创建一个名为MainActivity的Activity,并在其中动态注册一个广播接收器TimeChangeReceiver,用于接收系统时间变化的广播。当接收到广播时,弹出一个Toast提示用户。请写出MainActivityTimeChangeReceiver的代码。
    • 答案
      • MainActivity代码
        class MainActivity : AppCompatActivity() {
            private lateinit var timeChangeReceiver: TimeChangeReceiver
        
            override fun onCreate(savedInstanceState: Bundle?) {
                super.onCreate(savedInstanceState)
                setContentView(R.layout.activity_main)
        
                val intentFilter = IntentFilter("android.intent.action.TIME_TICK")
                timeChangeReceiver = TimeChangeReceiver()
                registerReceiver(timeChangeReceiver, intentFilter)
            }
        
            override fun onDestroy() {
                super.onDestroy()
                unregisterReceiver(timeChangeReceiver)
            }
        }
        
      • TimeChangeReceiver代码
        class TimeChangeReceiver : BroadcastReceiver() {
            override fun onReceive(context: Context, intent: Intent) {
                Toast.makeText(context, "Time has changed", Toast.LENGTH_SHORT).show()
            }
        }
        

第7章 数据存储全方案,详解持久化技术

重点知识

  • 数据持久化:将内存中的数据保存到存储设备中,确保数据在设备关机后仍然存在。
  • 文件存储
    • 数据保存到文件中,适合存储简单文本或二进制数据。
    • 示例:
      val output = openFileOutput("data", Context.MODE_PRIVATE)
      val writer = BufferedWriter(OutputStreamWriter(output))
      writer.use { it.write("Hello, World!") }
      
  • SharedPreferences存储
    • 使用键值对存储数据,适合存储简单的配置信息。
    • 示例:
      val editor = getSharedPreferences("data", Context.MODE_PRIVATE).edit()
      editor.putString("name", "Tom")
      editor.apply()
      
  • SQLite数据库存储
    • 轻量级关系型数据库,适合存储结构化数据。
    • 示例:
      class MyDatabaseHelper(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)"
          override fun onCreate(db: SQLiteDatabase) {
              db.execSQL(createBook)
          }
          override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
              db.execSQL("drop table if exists Book")
              onCreate(db)
          }
      }
      
  • 数据库操作
    • 插入数据
      val values = ContentValues().apply {
          put("name", "The Da Vinci Code")
          put("author", "Dan Brown")
          put("pages", 454)
          put("price", 16.96)
      }
      val db = MyDatabaseHelper(this, "BookStore.db", 1).writableDatabase
      db.insert("Book", null, values)
      
    • 更新数据
      val values = ContentValues().apply {
          put("price", 10.99)
      }
      db.update("Book", values, "name = ?", arrayOf("The Da Vinci Code"))
      
    • 删除数据
      db.delete("Book", "pages > ?", arrayOf("500"))
      
    • 查询数据
      val cursor = db.query("Book", null, null, null, null, null, null)
      if (cursor.moveToFirst()) {
          do {
              val name = cursor.getString(cursor.getColumnIndex("name"))
              val author = cursor.getString(cursor.getColumnIndex("author"))
              val pages = cursor.getInt(cursor.getColumnIndex("pages"))
              val price = cursor.getDouble(cursor.getColumnIndex("price"))
              Log.d("MainActivity", "book name is $name")
          } while (cursor.moveToNext())
      }
      cursor.close()
      

课后习题

单选题
  1. 在Android中,文件存储的数据默认保存在哪个目录下?答案:A

    • A. /data/data/<package name>/files/
    • B. /sdcard/
    • C. /data/data/<package name>/shared_prefs/
    • D. /data/data/<package name>/databases/
  2. SharedPreferences存储的数据以什么形式保存?答案:A

    • A. XML文件
    • B. 数据库
    • C. 二进制文件
    • D. 文本文件
  3. 在Android中,SQLiteOpenHelperonCreate()方法的作用是:答案:A

    • A. 创建数据库
    • B. 更新数据库
    • C. 删除数据库
    • D. 查询数据库
  4. 在Android中,SharedPreferencesedit()方法返回的是:答案:B

    • A. SharedPreferences
    • B. SharedPreferences.Editor
    • C. Context
    • D. Editor
  5. 在Android中,SQLiteOpenHelperonUpgrade()方法的作用是:答案:B

    • A. 创建数据库
    • B. 更新数据库
    • C. 删除数据库
    • D. 查询数据库
  6. 在Android中,SharedPreferencesapply()方法的作用是:答案:B

    • A. 保存数据
    • B. 提交数据
    • C. 清除数据
    • D. 查询数据
  7. 在Android中,SQLiteOpenHelperonCreate()方法中,db.execSQL()的作用是:答案:A

    • A. 执行SQL语句
    • B. 查询数据
    • C. 更新数据
    • D. 删除数据
  8. 在Android中,SharedPreferencesputString()方法的作用是:答案:B

    • A. 保存整型数据
    • B. 保存字符串数据
    • C. 保存布尔型数据
    • D. 保存浮点型数据
  9. 在Android中,SQLiteOpenHelperonUpgrade()方法中,db.execSQL("drop table if exists Book")的作用是:答案:C

    • A. 创建表
    • B. 更新表
    • C. 删除表
    • D. 查询表
  10. 在Android中,SharedPreferencesgetString()方法的作用是:答案:B

    • A. 保存字符串数据
    • B. 查询字符串数据
    • C. 更新字符串数据
    • D. 删除字符串数据
  11. 在Android中,SQLiteOpenHelperonCreate()方法中,db.execSQL(createBook)的作用是:答案:A

    • A. 创建表
    • B. 更新表
    • C. 删除表
    • D. 查询表
  12. 在Android中,SharedPreferencesputInt()方法的作用是:答案:A

    • A. 保存整型数据
    • B. 查询整型数据
    • C. 更新整型数据
    • D. 删除整型数据
  13. 在Android中,SQLiteOpenHelperonUpgrade()方法中,db.execSQL("drop table if exists Book")的作用是:答案:C

    • A. 创建表
    • B. 更新表
    • C. 删除表
    • D. 查询表
  14. 在Android中,SharedPreferencesgetString()方法的参数是:答案:B

    • A. 键值对
    • B. 键和默认值
    • C. 键和值
    • D. 键和类型
  15. 在Android中,SQLiteOpenHelperonCreate()方法中,db.execSQL(createBook)的作用是:答案:A

    • A. 创建表
    • B. 更新表
    • C. 删除表
    • D. 查询表
多选题
  1. Android中支持的数据存储方式包括以下哪些?答案:A, B, C

    • A. 文件存储
    • B. SharedPreferences存储
    • C. SQLite数据库存储
    • D. 网络存储
  2. 数据库操作中,以下哪些是SQLiteDatabase类提供的方法?答案:A, B, C, D

    • A. insert()
    • B. update()
    • C. delete()
    • D. query()
  3. 在Android中,以下哪些是SharedPreferences的常用方法?答案:A, B, C, D

    • A. putString()
    • B. putInt()
    • C. getString()
    • D. getInt()
  4. 在Android中,以下哪些是SQLiteOpenHelper的常用方法?答案:A, B, C

    • A. onCreate()
    • B. onUpgrade()
    • C. getWritableDatabase()
    • D. getReadableDatabase()
  5. 在Android中,以下哪些是SharedPreferences.Editor的常用方法?答案:A, B, C

    • A. putString()
    • B. putInt()
    • C. apply()
    • D. commit()
简答题
  1. 简述文件存储和SharedPreferences存储的区别。

    • 答案
      • 文件存储:用于存储复杂的数据或大型文件,如图片、视频等。
      • SharedPreferences存储:用于存储简单的键值对数据,适合存储配置信息。
  2. 请解释SQLiteOpenHelperonUpgrade()方法的作用。

    • 答案
      • 当数据库版本升级时,onUpgrade()方法被调用,用于更新数据库结构。
  3. 简述SharedPreferences的存储和读取逻辑。

    • 答案
      • 存储
        val editor = getSharedPreferences("data", Context.MODE_PRIVATE).edit()
        editor.putString("name", "Tom")
        editor.apply()
        
      • 读取
        val sharedPreferences = getSharedPreferences("data", Context.MODE_PRIVATE)
        val name = sharedPreferences.getString("name", "")
        
综合题
  1. 创建一个名为MainActivity的Activity,并在其中使用SharedPreferences存储用户输入的姓名和年龄。请写出MainActivity的代码,以及SharedPreferences的存储和读取逻辑。
    • 答案
      • MainActivity代码
        class MainActivity : AppCompatActivity() {
            private lateinit var sharedPreferences: SharedPreferences
            private lateinit var editor: SharedPreferences.Editor
        
            override fun onCreate(savedInstanceState: Bundle?) {
                super.onCreate(savedInstanceState)
                setContentView(R.layout.activity_main)
        
                sharedPreferences = getSharedPreferences("user_data", Context.MODE_PRIVATE)
                editor = sharedPreferences.edit()
        
                val nameEditText: EditText = findViewById(R.id.nameEditText)
                val ageEditText: EditText = findViewById(R.id.ageEditText)
                val saveButton: Button = findViewById(R.id.saveButton)
        
                saveButton.setOnClickListener {
                    val name = nameEditText.text.toString()
                    val age = ageEditText.text.toString()
                    editor.putString("name", name)
                    editor.putInt("age", age.toInt())
                    editor.apply()
                    Toast.makeText(this, "Data saved", Toast.LENGTH_SHORT).show()
                }
        
                val loadButton: Button = findViewById(R.id.loadButton)
                loadButton.setOnClickListener {
                    val name = sharedPreferences.getString("name", "")
                    val age = sharedPreferences.getInt("age", 0)
                    nameEditText.setText(name)
                    ageEditText.setText(age.toString())
                    Toast.makeText(this, "Data loaded", Toast.LENGTH_SHORT).show()
                }
            }
        }
        
      • activity_main布局文件
        <LinearLayout
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"
            android:padding="16dp">
        
            <EditText
                android:id="@+id/nameEditText"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="Enter name" />
        
            <EditText
                android:id="@+id/ageEditText"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="Enter age" />
        
            <Button
                android:id="@+id/saveButton"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="Save" />
        
            <Button
                android:id="@+id/loadButton"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="Load" />
        </LinearLayout>
        

第8章 跨程序共享数据,探究ContentProvider

重点知识

  • ContentProvider:Android四大组件之一,用于跨程序共享数据。
  • 权限机制
    • 安装时权限:用户安装应用时自动授予。
    • 运行时权限:用户在应用运行时授予。
    • 特殊权限:由系统或设备制造商定义。
  • 运行时权限请求
    • AndroidManifest.xml中声明权限。
    • 使用ContextCompat.checkSelfPermission()检查权限。
    • 使用ActivityCompat.requestPermissions()请求权限。
  • ContentResolver:用于访问ContentProvider提供的数据。
  • ContentProvider的创建
    • 继承ContentProvider类,重写onCreate()query()insert()update()delete()getType()方法。
  • UriMatcher:用于匹配ContentProvider的URI。

课后习题

单选题
  1. 在Android中,ContentProvider主要用于:答案:B

    • A. 网络通信
    • B. 跨程序共享数据
    • C. 数据存储
    • D. 用户界面
  2. 在Android中,运行时权限需要在何时请求?答案:B

    • A. 应用安装时
    • B. 应用运行时
    • C. 应用卸载时
    • D. 应用更新时
  3. 在Android中,ContentResolver的作用是:答案:C

    • A. 创建数据库
    • B. 更新UI
    • C. 访问ContentProvider提供的数据
    • D. 管理线程
  4. 在Android中,UriMatcher的作用是:答案:D

    • A. 创建数据库
    • B. 更新UI
    • C. 访问ContentProvider提供的数据
    • D. 匹配ContentProvider的URI
  5. 在Android中,ContentProvideronCreate()方法的作用是:答案:A

    • A. 初始化ContentProvider
    • B. 查询数据
    • C. 更新数据
    • D. 删除数据
  6. 在Android中,ContentProviderquery()方法的作用是:答案:B

    • A. 创建数据库
    • B. 查询数据
    • C. 更新数据
    • D. 删除数据
  7. 在Android中,ContentProviderinsert()方法的作用是:答案:C

    • A. 创建数据库
    • B. 查询数据
    • C. 插入数据
    • D. 删除数据
  8. 在Android中,ContentProviderupdate()方法的作用是:答案:C

    • A. 创建数据库
    • B. 查询数据
    • C. 更新数据
    • D. 删除数据
  9. 在Android中,ContentProviderdelete()方法的作用是:答案:D

    • A. 创建数据库
    • B. 查询数据
    • C. 更新数据
    • D. 删除数据
  10. 在Android中,ContentProvidergetType()方法的作用是:答案:E

    • A. 创建数据库
    • B. 查询数据
    • C. 更新数据
    • D. 删除数据
    • E. 获取数据的MIME类型
  11. 在Android中,ContentProvideronCreate()方法的作用是:答案:A

    • A. 初始化ContentProvider
    • B. 查询数据
    • C. 更新数据
    • D. 删除数据
  12. 在Android中,ContentProviderquery()方法的作用是:答案:B

    • A. 创建数据库
    • B. 查询数据
    • C. 更新数据
    • D. 删除数据
  13. 在Android中,ContentProviderinsert()方法的作用是:答案:C

    • A. 创建数据库
    • B. 查询数据
    • C. 插入数据
    • D. 删除数据
  14. 在Android中,ContentProviderupdate()方法的作用是:答案:C

    • A. 创建数据库
    • B. 查询数据
    • C. 更新数据
    • D. 删除数据
  15. 在Android中,ContentProviderdelete()方法的作用是:答案:D

    • A. 创建数据库
    • B. 查询数据
    • C. 更新数据
    • D. 删除数据
多选题
  1. 在Android中,以下哪些是ContentProvider的生命周期方法?答案:A, B, C, D, E

    • A. onCreate()
    • B. query()
    • C. insert()
    • D. update()
    • E. delete()
  2. 在Android中,以下哪些是ContentProvider的特性?答案:A, B, C

    • A. 跨程序共享数据
    • B. 提供数据访问接口
    • C. 支持多种数据类型
    • D. 管理线程
  3. 在Android中,以下哪些是ContentResolver的特性?答案:A, B, C

    • A. 查询数据
    • B. 插入数据
    • C. 更新数据
    • D. 删除数据
  4. 在Android中,以下哪些是UriMatcher的特性?答案:A, B, C

    • A. 匹配ContentProvider的URI
    • B. 提供数据访问接口
    • C. 支持多种数据类型
    • D. 管理线程
  5. 在Android中,以下哪些是ContentProvider的生命周期方法?答案:A, B, C, D, E

    • A. onCreate()
    • B. query()
    • C. insert()
    • D. update()
    • E. delete()
简答题
  1. 简述ContentProvider的作用。

    • 答案
      • ContentProvider用于跨程序共享数据,允许一个应用访问另一个应用的数据。
  2. 简述ContentResolver的作用。

    • 答案
      • ContentResolver用于访问ContentProvider提供的数据,通过Uri来查询、插入、更新和删除数据。
  3. 简述UriMatcher的作用。

    • 答案
      • UriMatcher用于匹配ContentProviderUri,通过addURI()方法添加匹配规则,简化Uri的处理逻辑。
综合题
  1. 创建一个名为MyProviderContentProvider,并定义一个名为table1的表。在table1表中存储用户信息,包括用户ID、用户名和用户年龄。请写出MyProvider的代码,以及在MainActivity中访问table1表的代码。
    • 答案
      • MyProvider代码

        class MyProvider : ContentProvider() {
            private lateinit var dbHelper: MyDatabaseHelper
        
            override fun onCreate(): Boolean {
                dbHelper = MyDatabaseHelper(context!!)
                return true
            }
        
            override fun query(uri: Uri, projection: Array<String>?, selection: String?, selectionArgs: Array<String>?, sortOrder: String?): Cursor? {
                return dbHelper.writableDatabase.query("table1", projection, selection, selectionArgs, null, null, sortOrder)
            }
        
            override fun insert(uri: Uri, values: ContentValues?): Uri? {
                val rowId = dbHelper.writableDatabase.insert("table1", null, values)
                return Uri.withAppendedPath(uri, rowId.toString())
            }
        
            override fun update(uri: Uri, values: ContentValues?, selection: String?, selectionArgs: Array<String>?): Int {
                return dbHelper.writableDatabase.update("table1", values, selection, selectionArgs)
            }
        
            override fun delete(uri: Uri, selection: String?, selectionArgs: Array<String>?): Int {
                return dbHelper.writableDatabase.delete("table1", selection, selectionArgs)
            }
        
            override fun getType(uri: Uri): String? {
                return when (uriMatcher.match(uri)) {
                    1 -> "vnd.android.cursor.dir/vnd.com.example.app.provider.table1"
                    2 -> "vnd.android.cursor.item/vnd.com.example.app.provider.table1"
                    else -> null
                }
            }
        }
        
      • MainActivity代码

        class MainActivity : AppCompatActivity() {
            override fun onCreate(savedInstanceState: Bundle?) {
                super.onCreate(savedInstanceState)
                setContentView(R.layout.activity_main)
        
                val user = User("John Doe", 30)
                val values = ContentValues().apply {
                    put("name", user.name)
                    put("age", user.age)
                }
        
                val uri = Uri.parse("content://com.example.app.provider/table1")
                contentResolver.insert(uri, values)
        
                val cursor = contentResolver.query(uri, null, null, null, null)
                cursor?.use {
                    if (it.moveToFirst()) {
                        do {
                            val name = it.getString(it.getColumnIndex("name"))
                            val age = it.getInt(it.getColumnIndex("age"))
                            Log.d("MainActivity", "Name: $name, Age: $age")
                        } while (it.moveToNext())
                    }
                }
            }
        }
        
      • MyDatabaseHelper代码

        class MyDatabaseHelper(context: Context) : SQLiteOpenHelper(context, "MyDatabase.db", null, 1) {
            private val createTable1 = "CREATE TABLE table1 (" +
                    "id INTEGER PRIMARY KEY AUTOINCREMENT," +
                    "name TEXT," +
                    "age INTEGER)"
        
            override fun onCreate(db: SQLiteDatabase) {
                db.execSQL(createTable1)
            }
        
            override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
                db.execSQL("DROP TABLE IF EXISTS table1")
                onCreate(db)
            }
        }
        
      • AndroidManifest.xml注册代码

        <application
            ...>
            <provider
                android:name=".MyProvider"
                android:authorities="com.example.app.provider"
                android:enabled="true"
                android:exported="true" />
        </application>
        

第9章 丰富你的程序,运用手机多媒体

重点知识

  • 通知
    • 通知渠道:Android 8.0引入的概念,每条通知必须属于一个通知渠道。
    • 创建通知渠道
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
          val channel = NotificationChannel("channel_id", "channel_name", NotificationManager.IMPORTANCE_DEFAULT)
          val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
          manager.createNotificationChannel(channel)
      }
      
    • 发送通知
      val notification = NotificationCompat.Builder(this, "channel_id")
          .setContentTitle("Title")
          .setContentText("Text")
          .setSmallIcon(R.drawable.ic_notification)
          .build()
      val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
      manager.notify(1, notification)
      
  • 调用摄像头和相册
    • 调用摄像头拍照
      val intent = Intent("android.media.action.IMAGE_CAPTURE")
      intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri)
      startActivityForResult(intent, REQUEST_CODE)
      
    • 从相册中选择图片
      val intent = Intent(Intent.ACTION_OPEN_DOCUMENT)
      intent.addCategory(Intent.CATEGORY_OPENABLE)
      intent.type = "image/*"
      startActivityForResult(intent, REQUEST_CODE)
      
  • 播放多媒体文件
    • 播放音频
      val mediaPlayer = MediaPlayer()
      val assetManager = assets
      val fd = assetManager.openFd("music.mp3")
      mediaPlayer.setDataSource(fd.fileDescriptor, fd.startOffset, fd.length)
      mediaPlayer.prepare()
      mediaPlayer.start()
      
    • 播放视频
      val uri = Uri.parse("android.resource://$packageName/${R.raw.video}")
      videoView.setVideoURI(uri)
      videoView.start()
      

课后习题

单选题
  1. 在Android中,通知渠道是在哪个版本中引入的?答案:B

    • A. Android 7.0
    • B. Android 8.0
    • C. Android 9.0
    • D. Android 10.0
  2. 在Android中,调用系统相机拍照时,需要使用以下哪个Intent Action?答案:D

    • A. Intent.ACTION_VIEW
    • B. Intent.ACTION_SEND
    • C. Intent.ACTION_OPEN_DOCUMENT
    • D. android.media.action.IMAGE_CAPTURE
  3. 在Android中,播放音频文件时,通常使用哪个类?答案:A

    • A. MediaPlayer
    • B. VideoView
    • C. AudioManager
    • D. SoundPool
  4. 在Android中,通知的最小图标是通过哪个方法设置的?答案:C

    • A. setLargeIcon()
    • B. setBigIcon()
    • C. setSmallIcon()
    • D. setIcon()
  5. 在Android中,MediaPlayerprepare()方法的作用是:答案:B

    • A. 开始播放
    • B. 准备播放
    • C. 暂停播放
    • D. 停止播放
  6. 在Android中,MediaPlayerstart()方法的作用是:答案:A

    • A. 开始播放
    • B. 准备播放
    • C. 暂停播放
    • D. 停止播放
  7. 在Android中,MediaPlayerpause()方法的作用是:答案:C

    • A. 开始播放
    • B. 准备播放
    • C. 暂停播放
    • D. 停止播放
  8. 在Android中,MediaPlayerstop()方法的作用是:答案:D

    • A. 开始播放
    • B. 准备播放
    • C. 暂停播放
    • D. 停止播放
  9. 在Android中,MediaPlayerrelease()方法的作用是:答案:E

    • A. 开始播放
    • B. 准备播放
    • C. 暂停播放
    • D. 停止播放
    • E. 释放资源
  10. 在Android中,MediaPlayerisPlaying()方法的作用是:答案:F

    • A. 开始播放
    • B. 准备播放
    • C. 暂停播放
    • D. 停止播放
    • E. 释放资源
    • F. 检查是否正在播放
  11. 在Android中,通知的最小图标是通过哪个方法设置的?答案:C

    • A. setLargeIcon()
    • B. setBigIcon()
    • C. setSmallIcon()
    • D. setIcon()
  12. 在Android中,MediaPlayerprepare()方法的作用是:答案:B

    • A. 开始播放
    • B. 准备播放
    • C. 暂停播放
    • D. 停止播放
  13. 在Android中,MediaPlayerstart()方法的作用是:答案:A

    • A. 开始播放
    • B. 准备播放
    • C. 暂停播放
    • D. 停止播放
  14. 在Android中,MediaPlayerpause()方法的作用是:答案:C

    • A. 开始播放
    • B. 准备播放
    • C. 暂停播放
    • D. 停止播放
  15. 在Android中,MediaPlayerstop()方法的作用是:答案:D

    • A. 开始播放
    • B. 准备播放
    • C. 暂停播放
    • D. 停止播放
多选题
  1. 在Android中,以下哪些是通知的组成部分?答案:A, B, C, D

    • A. 通知渠道
    • B. 通知内容
    • C. 通知图标
    • D. 通知ID
  2. 在Android中,以下哪些是播放多媒体文件的类?答案:A, B

    • A. MediaPlayer
    • B. VideoView
    • C. AudioManager
    • D. SoundPool
  3. 在Android中,以下哪些是MediaPlayer的常用方法?答案:A, B, C, D, E, F

    • A. prepare()
    • B. start()
    • C. pause()
    • D. stop()
    • E. release()
    • F. isPlaying()
  4. 在Android中,以下哪些是调用摄像头拍照的步骤?答案:A, B, C

    • A. 创建Intent
    • B. 设置输出路径
    • C. 调用startActivityForResult()
    • D. 调用startActivity()
  5. 在Android中,以下哪些是播放视频的步骤?答案:A, B, C

    • A. 创建VideoView
    • B. 设置视频URI
    • C. 调用start()
    • D. 调用pause()
简答题
  1. 简述如何在Android中创建通知渠道。

    • 答案
      • 在Android 8.0及以上版本中,需要创建通知渠道。通过NotificationChannel类创建渠道,并通过NotificationManager注册渠道。
  2. 简述如何在Android中调用系统相机拍照。

    • 答案
      • 创建一个Intent,指定android.media.action.IMAGE_CAPTURE作为action,并设置输出路径。通过startActivityForResult()启动相机应用。
  3. 简述如何在Android中播放音频文件。

    • 答案
      • 使用MediaPlayer类播放音频文件。通过setDataSource()设置音频文件路径,调用prepare()方法准备播放,最后调用start()方法开始播放。
综合题
  1. 创建一个名为MainActivity的Activity,并在其中实现以下功能:
    • 创建一个通知渠道,并发送一个通知。
    • 调用系统相机拍照,并将拍摄的照片显示在ImageView中。
    • 播放一个音频文件。
    • 请写出MainActivity的代码,以及相关布局文件。
    • 答案
      • MainActivity代码

        class MainActivity : AppCompatActivity() {
            private lateinit var imageView: ImageView
            private lateinit var mediaPlayer: MediaPlayer
        
            override fun onCreate(savedInstanceState: Bundle?) {
                super.onCreate(savedInstanceState)
                setContentView(R.layout.activity_main)
        
                // Create notification channel
                createNotificationChannel()
        
                // Take photo
                val takePhotoButton: Button = findViewById(R.id.takePhotoButton)
                takePhotoButton.setOnClickListener {
                    val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
                    startActivityForResult(intent, REQUEST_CODE)
                }
        
                // Play audio
                val playAudioButton: Button = findViewById(R.id.playAudioButton)
                playAudioButton.setOnClickListener {
                    mediaPlayer = MediaPlayer.create(this, R.raw.music)
                    mediaPlayer.start()
                }
            }
        
            override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
                super.onActivityResult(requestCode, resultCode, data)
                if (requestCode == REQUEST_CODE && resultCode == Activity.RESULT_OK) {
                    val bitmap = data?.extras?.get("data") as Bitmap
                    imageView.setImageBitmap(bitmap)
                }
            }
        
            private fun createNotificationChannel() {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                    val channel = NotificationChannel("channel_id", "channel_name", NotificationManager.IMPORTANCE_DEFAULT)
                    val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
                    manager.createNotificationChannel(channel)
                    val notification = NotificationCompat.Builder(this, "channel_id")
                        .setContentTitle("Title")
                        .setContentText("Text")
                        .setSmallIcon(R.drawable.ic_notification)
                        .build()
                    manager.notify(1, notification)
                }
            }
        }
        
      • activity_main布局文件

        <LinearLayout
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"
            android:padding="16dp">
        
            <Button
                android:id="@+id/takePhotoButton"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="Take Photo" />
        
            <ImageView
                android:id="@+id/imageView"
                android:layout_width="match_parent"
                android:layout_height="200dp" />
        
            <Button
                android:id="@+id/playAudioButton"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="Play Audio" />
        </LinearLayout>
        

第10章 后台默默的劳动者,探究Service

重点知识

  • Service:Android四大组件之一,用于后台执行长时间运行的任务。
  • Service启动方式
    • startService:启动服务,服务可以在后台无限期运行。
    • bindService:绑定服务,允许组件与服务进行交互。
  • Service生命周期
    • onCreate():服务创建时调用。
    • onStartCommand():服务启动时调用。
    • onDestroy():服务销毁时调用。
  • 前台Service
    • 使用startForeground()启动,显示通知图标。
  • 多线程编程
    • 继承Thread类:创建线程。
    • 实现Runnable接口:创建线程。
    • Handler:在子线程中更新UI。
  • 协程:Kotlin语言的特性,用于异步操作。

课后习题

单选题
  1. 在Android中,Service主要用于:答案:B

    • A. 用户界面
    • B. 后台任务
    • C. 数据存储
    • D. 网络通信
  2. 在Android中,Service的生命周期方法onCreate()的作用是:答案:A

    • A. 创建服务
    • B. 启动服务
    • C. 销毁服务
    • D. 绑定服务
  3. 在Android中,Service的生命周期方法onStartCommand()的作用是:答案:B

    • A. 创建服务
    • B. 启动服务
    • C. 销毁服务
    • D. 绑定服务
  4. 在Android中,Service的生命周期方法onDestroy()的作用是:答案:C

    • A. 创建服务
    • B. 启动服务
    • C. 销毁服务
    • D. 绑定服务
  5. 在Android中,Service的启动方式startService的作用是:答案:B

    • A. 创建服务
    • B. 启动服务
    • C. 销毁服务
    • D. 绑定服务
  6. 在Android中,Service的启动方式bindService的作用是:答案:D

    • A. 创建服务
    • B. 启动服务
    • C. 销毁服务
    • D. 绑定服务
  7. 在Android中,ServicestartForeground()方法的作用是:答案:A

    • A. 将服务置于前台
    • B. 将服务置于后台
    • C. 创建服务
    • D. 销毁服务
  8. 在Android中,ServicestopSelf()方法的作用是:答案:C

    • A. 创建服务
    • B. 启动服务
    • C. 停止服务
    • D. 绑定服务
  9. 在Android中,ServiceunbindService()方法的作用是:答案:D

    • A. 创建服务
    • B. 启动服务
    • C. 停止服务
    • D. 解绑服务
  10. 在Android中,ServicebindService()方法的作用是:答案:D

    • A. 创建服务
    • B. 启动服务
    • C. 停止服务
    • D. 绑定服务
  11. 在Android中,ServicestartService()方法的作用是:答案:B

    • A. 创建服务
    • B. 启动服务
    • C. 停止服务
    • D. 绑定服务
  12. 在Android中,ServiceonCreate()方法的作用是:答案:A

    • A. 创建服务
    • B. 启动服务
    • C. 停止服务
    • D. 绑定服务
  13. 在Android中,ServiceonStartCommand()方法的作用是:答案:B

    • A. 创建服务
    • B. 启动服务
    • C. 停止服务
    • D. 绑定服务
  14. 在Android中,ServiceonDestroy()方法的作用是:答案:C

    • A. 创建服务
    • B. 启动服务
    • C. 停止服务
    • D. 绑定服务
  15. 在Android中,ServicebindService()方法的作用是:答案:D

    • A. 创建服务
    • B. 启动服务
    • C. 停止服务
    • D. 绑定服务
多选题
  1. 在Android中,以下哪些是Service的生命周期方法?答案:A, B, C

    • A. onCreate()
    • B. onStartCommand()
    • C. onDestroy()
    • D. onPause()
  2. 在Android中,以下哪些是Service的启动方式?答案:A, B

    • A. startService()
    • B. bindService()
    • C. stopService()
    • D. unbindService()
  3. 在Android中,以下哪些是多线程编程的方法?答案:A, B, C

    • A. 继承Thread
    • B. 实现Runnable接口
    • C. 使用Handler
    • D. 使用AsyncTask
  4. 在Android中,以下哪些是Service的特性?答案:A, B, C

    • A. 可以在后台运行
    • B. 可以启动和停止
    • C. 可以绑定和解绑
    • D. 可以显示UI
  5. 在Android中,以下哪些是Service的生命周期方法?答案:A, B, C

    • A. onCreate()
    • B. onStartCommand()
    • C. onDestroy()
    • D. onPause()
简答题
  1. 简述Service的生命周期。

    • 答案
      • onCreate():服务创建时调用。
      • onStartCommand():服务启动时调用。
      • onDestroy():服务销毁时调用。
  2. 简述Service的启动方式。

    • 答案
      • startService():启动服务,服务可以在后台无限期运行。
      • bindService():绑定服务,允许组件与服务进行交互。
  3. 简述多线程编程的方法。

    • 答案
      • 继承Thread类:创建线程。
      • 实现Runnable接口:创建线程。
      • 使用Handler:在子线程中更新UI。
综合题
  1. 创建一个名为MyServiceService,并在其中实现一个后台任务,每隔5秒打印一次当前时间。请写出MyService的代码,以及在MainActivity中启动和停止MyService的代码。
    • 答案
      • MyService代码

        class MyService : Service() {
            private lateinit var handler: Handler
            private lateinit var runnable: Runnable
        
            override fun onCreate() {
                super.onCreate()
                handler = Handler(Looper.getMainLooper())
                runnable = object : Runnable {
                    override fun run() {
                        Log.d("MyService", "Current time: ${SimpleDateFormat("HH:mm:ss", Locale.getDefault()).format(Date())}")
                        handler.postDelayed(this, 5000)
                    }
                }
                handler.post(runnable)
            }
        
            override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
                return START_STICKY
            }
        
            override fun onDestroy() {
                super.onDestroy()
                handler.removeCallbacks(runnable)
            }
        
            override fun onBind(intent: Intent?): IBinder? {
                return null
            }
        }
        
      • MainActivity代码

        class MainActivity : AppCompatActivity() {
            override fun onCreate(savedInstanceState: Bundle?) {
                super.onCreate(savedInstanceState)
                setContentView(R.layout.activity_main)
        
                val startServiceButton: Button = findViewById(R.id.startServiceButton)
                startServiceButton.setOnClickListener {
                    val intent = Intent(this, MyService::class.java)
                    startService(intent)
                }
        
                val stopServiceButton: Button = findViewById(R.id.stopServiceButton)
                stopServiceButton.setOnClickListener {
                    val intent = Intent(this, MyService::class.java)
                    stopService(intent)
                }
            }
        }
        
      • activity_main布局文件

        <LinearLayout
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"
            android:padding="16dp">
        
            <Button
                android:id="@+id/startServiceButton"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="Start Service" />
        
            <Button
                android:id="@+id/stopServiceButton"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="Stop Service" />
        </LinearLayout>
        
      • AndroidManifest.xml注册代码

        <application
            ...>
            <service android:name=".MyService" />
        </application>
        

第11章 看看精彩的世界,使用网络技术

重点知识

  • WebView

    • 用于在应用中嵌入网页。
    • 示例:
      val webView: WebView = findViewById(R.id.webView)
      webView.settings.javaScriptEnabled = true
      webView.webViewClient = WebViewClient()
      webView.loadUrl("https://www.example.com")
      
  • 网络请求

    • HttpURLConnection
      val url = URL("https://www.example.com")
      val connection = url.openConnection() as HttpURLConnection
      connection.requestMethod = "GET"
      val input = connection.inputStream
      connection.disconnect()
      
    • OkHttp
      val client = OkHttpClient()
      val request = Request.Builder().url("https://www.example.com").build()
      val response = client.newCall(request).execute()
      val responseData = response.body?.string()
      
  • 数据解析

    • XML解析

      • Pull解析
        val factory = XmlPullParserFactory.newInstance()
        val parser = factory.newPullParser()
        parser.setInput(StringReader(xmlData))
        var eventType = parser.eventType
        while (eventType != XmlPullParser.END_DOCUMENT) {
            when (eventType) {
                XmlPullParser.START_TAG -> {
                    when (parser.name) {
                        "tag" -> {
                            val value = parser.nextText()
                            // 处理数据
                        }
                    }
                }
            }
            eventType = parser.next()
        }
        
      • SAX解析
        val saxParser = SAXParserFactory.newInstance().newSAXParser()
        val handler = MyHandler()
        saxParser.parse(xmlData, handler)
        
    • JSON解析

      • JSONObject
        val jsonArray = JSONArray(jsonData)
        for (i in 0 until jsonArray.length()) {
            val jsonObject = jsonArray.getJSONObject(i)
            val id = jsonObject.getString("id")
            val name = jsonObject.getString("name")
            val version = jsonObject.getString("version")
            // 处理数据
        }
        
      • GSON
        val type = object : TypeToken<List<MyObject>>() {}.type
        val list = Gson().fromJson<List<MyObject>>(jsonData, type)
        
  • Retrofit

    • 用于网络请求的库,基于OkHttp。
    • 示例:
      val retrofit = Retrofit.Builder()
          .baseUrl("https://api.example.com/")
          .addConverterFactory(GsonConverterFactory.create())
          .build()
      val service = retrofit.create(MyService::class.java)
      service.getData().enqueue(object : Callback<MyData> {
          override fun onResponse(call: Call<MyData>, response: Response<MyData>) {
              // 处理响应
          }
      
          override fun onFailure(call: Call<MyData>, t: Throwable) {
              // 处理错误
          }
      })
      

课后习题

单选题
  1. 在Android中,WebView用于:答案:B

    • A. 显示图片
    • B. 显示网页
    • C. 播放视频
    • D. 显示文本
  2. 在Android中,HttpURLConnection用于:答案:B

    • A. 数据存储
    • B. 网络请求
    • C. UI显示
    • D. 线程管理
  3. 在Android中,OkHttp是一个:答案:B

    • A. 数据库
    • B. 网络请求库
    • C. UI框架
    • D. 多线程库
  4. 在Android中,Retrofit是一个:答案:B

    • A. 数据库
    • B. 网络请求库
    • C. UI框架
    • D. 多线程库
  5. 在Android中,WebViewloadUrl()方法的作用是:答案:B

    • A. 加载图片
    • B. 加载网页
    • C. 加载视频
    • D. 加载文本
  6. 在Android中,HttpURLConnectiongetInputStream()方法的作用是:答案:B

    • A. 获取输出流
    • B. 获取输入流
    • C. 获取错误流
    • D. 获取响应代码
  7. 在Android中,OkHttpnewCall()方法的作用是:答案:B

    • A. 创建一个新的请求
    • B. 创建一个新的调用
    • C. 创建一个新的响应
    • D. 创建一个新的连接
  8. 在Android中,Retrofitcreate()方法的作用是:答案:B

    • A. 创建一个新的请求
    • B. 创建一个新的服务
    • C. 创建一个新的响应
    • D. 创建一个新的连接
  9. 在Android中,WebViewsetJavaScriptEnabled()方法的作用是:答案:B

    • A. 启用图片
    • B. 启用JavaScript
    • C. 启用视频
    • D. 启用文本
  10. 在Android中,HttpURLConnectiondisconnect()方法的作用是:答案:D

    • A. 连接网络
    • B. 发送请求
    • C. 接收响应
    • D. 断开连接
  11. 在Android中,OkHttpexecute()方法的作用是:答案:B

    • A. 创建一个新的请求
    • B. 执行请求
    • C. 创建一个新的响应
    • D. 创建一个新的连接
  12. 在Android中,Retrofitenqueue()方法的作用是:答案:B

    • A. 创建一个新的请求
    • B. 异步执行请求
    • C. 创建一个新的响应
    • D. 创建一个新的连接
  13. 在Android中,WebViewwebViewClient的作用是:答案:B

    • A. 管理网页加载
    • B. 管理网页客户端
    • C. 管理网页请求
    • D. 管理网页响应
  14. 在Android中,HttpURLConnectionsetRequestMethod()方法的作用是:答案:B

    • A. 设置请求头
    • B. 设置请求方法
    • C. 设置请求体
    • D. 设置请求参数
  15. 在Android中,OkHttpRequest.Builder()的作用是:答案:B

    • A. 创建一个新的请求
    • B. 构建一个新的请求
    • C. 创建一个新的响应
    • D. 创建一个新的连接
多选题
  1. 在Android中,以下哪些是网络请求的库?答案:A, B, C

    • A. HttpURLConnection
    • B. OkHttp
    • C. Retrofit
    • D. WebView
  2. 在Android中,以下哪些是数据解析的方式?答案:A, B

    • A. XML解析
    • B. JSON解析
    • C. HTML解析
    • D. CSS解析
  3. 在Android中,以下哪些是WebView的特性?答案:A, B, C

    • A. 显示网页
    • B. 支持JavaScript
    • C. 支持HTML5
    • D. 支持CSS3
  4. 在Android中,以下哪些是HttpURLConnection的特性?答案:A, B, C

    • A. 发送GET请求
    • B. 发送POST请求
    • C. 获取响应数据
    • D. 支持异步操作
  5. 在Android中,以下哪些是OkHttp的特性?答案:A, B, C

    • A. 发送GET请求
    • B. 发送POST请求
    • C. 获取响应数据
    • D. 支持异步操作
简答题
  1. 简述WebView的用途。

    • 答案
      • WebView用于在应用中嵌入网页,支持显示HTML内容和执行JavaScript。
  2. 简述HttpURLConnectionOkHttp的区别。

    • 答案
      • HttpURLConnection是Android官方提供的网络请求类,功能较为基础。
      • OkHttp是一个第三方库,提供了更丰富的功能和更好的性能。
  3. 简述Retrofit的作用。

    • 答案
      • Retrofit是一个基于OkHttp的网络请求库,提供了更简洁的API和自动解析JSON的功能。
综合题
  1. 创建一个名为MainActivity的Activity,并在其中实现以下功能:
    • 使用WebView加载一个网页。
    • 使用HttpURLConnection发送一个GET请求,并将返回的数据显示在TextView中。
    • 使用OkHttp发送一个GET请求,并将返回的数据解析为JSON格式。
    • 请写出MainActivity的代码,以及相关布局文件。
    • 答案
      • MainActivity代码

        class MainActivity : AppCompatActivity() {
            private lateinit var webView: WebView
            private lateinit var textView: TextView
        
            override fun onCreate(savedInstanceState: Bundle?) {
                super.onCreate(savedInstanceState)
                setContentView(R.layout.activity_main)
        
                webView = findViewById(R.id.webView)
                textView = findViewById(R.id.textView)
        
                // Load web page
                webView.settings.javaScriptEnabled = true
                webView.webViewClient = WebViewClient()
                webView.loadUrl("https://www.example.com")
        
                // Send HTTP request using HttpURLConnection
                val sendRequestButton: Button = findViewById(R.id.sendRequestButton)
                sendRequestButton.setOnClickListener {
                    thread {
                        val url = URL("https://www.example.com")
                        val connection = url.openConnection() as HttpURLConnection
                        connection.requestMethod = "GET"
                        val input = connection.inputStream
                        val response = inputStreamToString(input)
                        runOnUiThread {
                            textView.text = response
                        }
                    }
                }
        
                // Send HTTP request using OkHttp
                val sendOkHttpRequestButton: Button = findViewById(R.id.sendOkHttpRequestButton)
                sendOkHttpRequestButton.setOnClickListener {
                    thread {
                        val client = OkHttpClient()
                        val request = Request.Builder().url("https://www.example.com").build()
                        val response = client.newCall(request).execute()
                        val responseData = response.body?.string()
                        if (responseData != null) {
                            val jsonData = parseJSON(responseData)
                            runOnUiThread {
                                textView.text = jsonData
                            }
                        }
                    }
                }
            }
        
            private fun inputStreamToString(input: InputStream): String {
                val reader = BufferedReader(InputStreamReader(input))
                val sb = StringBuilder()
                reader.use {
                    reader.forEachLine {
                        sb.append(it)
                    }
                }
                return sb.toString()
            }
        
            private fun parseJSON(responseData: String): String {
                val jsonArray = JSONArray(responseData)
                val sb = StringBuilder()
                for (i in 0 until jsonArray.length()) {
                    val jsonObject = jsonArray.getJSONObject(i)
                    val id = jsonObject.getString("id")
                    val name = jsonObject.getString("name")
                    val version = jsonObject.getString("version")
                    sb.append("ID: $id, Name: $name, Version: $version\n")
                }
                return sb.toString()
            }
        }
        
      • activity_main布局文件

        <LinearLayout
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"
            android:padding="16dp">
        
            <WebView
                android:id="@+id/webView"
                android:layout_width="match_parent"
                android:layout_height="200dp" />
        
            <TextView
                android:id="@+id/textView"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />
        
            <Button
                android:id="@+id/sendRequestButton"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="Send HTTP Request" />
        
            <Button
                android:id="@+id/sendOkHttpRequestButton"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="Send OkHttp Request" />
        </LinearLayout>
        
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐