当前位置: 首页 > web >正文

2025Android开发面试题

在面试中,协程(Coroutines)是一个高频考点,尤其在Android开发领域。它是一种轻量级的并发编程方案,能够简化异步操作的代码逻辑,解决传统回调地狱(Callback Hell)问题。以下从核心概念、优势、关键API及实际场景等方面进行梳理,帮助面试应答:

一、协程的核心概念

协程本质是可以暂停和恢复的函数,运行在指定的线程上下文中(如主线程、IO线程),但本身并不直接对应线程,而是由协程调度器(Dispatcher) 管理线程分配。

  • 暂停(Suspend):函数执行到某个节点时暂停,释放线程资源(线程可去执行其他任务)。
  • 恢复(Resume):当异步操作完成(如网络请求返回、数据库查询结束),函数从暂停处继续执行。

二、协程的优势(对比传统方案)

  1. 代码简洁,可读性高
    异步操作用同步代码的线性逻辑编写,避免多层嵌套回调(如AsyncTaskonPostExecute或RxJava的链式调用)。
    例:网络请求+数据库存储的异步流程,用协程可写成连续的函数调用,而非嵌套回调。

  2. 轻量高效
    一个进程中可以创建数万甚至数十万协程(内存占用仅几KB),而线程创建数量有限(通常数百个,每个线程占几MB内存)。
    适合高并发场景(如批量网络请求、大量数据处理)。

  3. 结构化并发(Structured Concurrency)
    协程具有明确的生命周期作用域(CoroutineScope),父协程可管理子协程的生命周期(如取消父协程时,自动取消所有子协程),避免内存泄漏。

  4. 线程切换灵活
    通过调度器(Dispatcher)可轻松指定协程运行的线程(如主线程更新UI,IO线程执行耗时操作),无需手动调用runOnUiThreadHandler

三、关键API与核心组件

  1. CoroutineScope(协程作用域)
    协程必须在CoroutineScope中启动,用于管理协程的生命周期(如Activity销毁时取消协程)。
    常用作用域:

    • GlobalScope:全局作用域,生命周期与应用一致(不推荐,易导致内存泄漏)。
    • 自定义作用域:结合JobDispatcher,如val scope = CoroutineScope(Dispatchers.Main + Job()),可通过scope.cancel()取消所有子协程。
  2. suspend关键字
    标记可暂停的函数,仅能在协程或其他suspend函数中调用。
    例:suspend fun fetchData(): String { ... }(内部可能包含网络请求等异步操作)。

  3. 调度器(Dispatcher
    决定协程运行的线程:

    • Dispatchers.Main:Android主线程(用于更新UI,需依赖androidx.lifecycle:lifecycle-viewmodel-ktx等库)。
    • Dispatchers.IO:IO线程池(适合网络请求、数据库操作等耗时操作)。
    • Dispatchers.Default:默认线程池(适合CPU密集型任务,如数据计算)。
    • Dispatchers.Unconfined:不限制线程(跟随当前线程执行,较少使用)。
  4. 启动协程的方式

    • launch:启动一个不返回结果的协程(用于执行耗时操作后更新UI),返回Job对象(可用于取消协程)。
    • async/await:启动一个返回结果的协程,async返回Deferred对象,调用await()获取结果(会暂停当前协程,直到结果返回)。

四、实际场景示例(Android)

场景1:简单的异步任务(IO操作+UI更新)
// 自定义协程作用域(与Activity生命周期绑定)
class MyActivity : AppCompatActivity() {private val scope = CoroutineScope(Dispatchers.Main + Job())override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)// 启动协程scope.launch {// 1. 切换到IO线程执行网络请求(suspend函数内部通过withContext指定Dispatcher)val data = fetchNetworkData() // 调用suspend函数// 2. 自动切换回主线程更新UI(因为scope的Dispatcher是Main)updateUI(data)}}// 定义suspend函数(内部处理IO操作)private suspend fun fetchNetworkData(): String {// withContext切换到IO线程,执行后自动返回原线程(此处原线程是Main)return withContext(Dispatchers.IO) {// 模拟网络请求URL("https://example.com/data").readText()}}private fun updateUI(data: String) {findViewById<TextView>(R.id.textView).text = data}// 页面销毁时取消协程,避免内存泄漏override fun onDestroy() {super.onDestroy()scope.cancel()}
}
场景2:并行任务(多个异步操作同时执行)
scope.launch {// 启动两个并行的异步任务val deferred1 = async(Dispatchers.IO) { fetchData1() }val deferred2 = async(Dispatchers.IO) { fetchData2() }// 等待两个任务都完成后,合并结果(await()会暂停当前协程)val result1 = deferred1.await()val result2 = deferred2.await()val combinedResult = "$result1 + $result2"// 更新UIupdateUI(combinedResult)
}

五、协程的取消与异常处理

  1. 取消机制

    • 协程通过Job对象取消:job.cancel(),取消后协程会抛出CancellationException,需在suspend函数中正确响应(如定期检查isActive状态)。
    • 结构化取消:父协程取消时,所有子协程自动取消(如scope.cancel()会取消其启动的所有协程)。
  2. 异常处理

    • launch中通过try-catch捕获异常,或使用CoroutineExceptionHandler统一处理。
    • async中异常需在await()时捕获(因为异常会被封装在Deferred中)。

六、总结(面试核心点)

  • 协程是轻量级的并发方案,通过暂停/恢复机制简化异步代码。
  • 核心优势:代码简洁、轻量高效、结构化并发、线程切换灵活。
  • 关键组件:CoroutineScope(作用域)、suspend(暂停函数)、Dispatcher(调度器)、launch/async(启动方式)。
  • 实际应用:替代AsyncTask、RxJava等,处理网络请求、数据库操作等异步场景,需注意生命周期管理(避免内存泄漏)。

掌握这些要点,能清晰阐述协程的设计思想和实际价值,应对面试中的相关问题。
Socket 是网络编程中的核心概念,面试中常围绕其基本原理、通信流程、阻塞/非阻塞模式、TCP/UDP 区别等展开。以下是高频考点梳理,结合原理和实践问题:

一、Socket 基本概念

  • 定义:Socket(套接字)是操作系统提供的网络编程接口,用于实现不同主机(或同一主机不同进程)之间的双向通信。它封装了 TCP/IP 协议的底层细节,提供简单的编程接口(如 read/write/connect 等)。
  • 核心作用:标识网络中的一个通信端点,由 IP 地址 + 端口号 唯一确定(如 192.168.1.1:8080)。

二、TCP 与 UDP 的区别(必问)

Socket 基于 TCP 或 UDP 协议工作,二者差异是面试重点:

特性 TCP(传输控制协议) UDP(用户数据报协议)
连接性 面向连接(三次握手建立连接) 无连接(直接发送,不确认对方是否接收)
可靠性 可靠(重传机制、流量控制、拥塞控制) 不可靠(丢包不重传,无序)
数据边界 无(流式数据,需应用层处理边界) 有(每个数据报独立,边界清晰)
速度 较慢(因确认机制) 较快(无额外开销)
适用场景 文件传输、HTTP/HTTPS、登录等 实时通信(视频/语音)、广播、DNS 等

三、TCP Socket 通信流程(经典面试题)

TCP 是面向连接的协议,通信需经过“建立连接→数据传输→断开连接”三个阶段,以 C/S 架构为例:

1. 服务器端流程
// 1. 创建 ServerSocket,绑定端口(监听端口)
ServerSocket serverSocket = new ServerSocket(8080);// 2. 阻塞等待客户端连接(accept() 方法)
Socket clientSocket = serverSocket.accept(); // 返回与客户端通信的 Socket// 3. 获取输入流(读客户端数据)和输出流(向客户端写数据)
InputStream in = clientSocket.getInputStream();
OutputStream out = clientSocket.getOutputStream();// 4. 读写数据(业务逻辑)
// ...// 5. 关闭资源(先关客户端 Socket,再关 ServerSocket)
clientSocket.close();
serverSocket.close
http://www.xdnf.cn/news/20250.html

相关文章:

  • 目标检测双雄:一阶段与二阶段检测器全解析
  • Nextcloud 实战:打造属于你的私有云与在线协作平台
  • Oracle 数据库:视图与索引
  • 没 iCloud, 如何数据从iPhone转移到iPhone
  • ZooKeeper架构深度解析:分布式协调服务的核心设计与实现
  • Conda环境隔离和PyCharm配置,完美同时运行PaddlePaddle和PyTorch
  • 机器学习(七)决策树-分类
  • [论文阅读] 人工智能 + 软件工程 | 当ISO 26262遇上AI:电动车安全标准的新玩法
  • 中国移动浪潮云电脑CD1000-系统全分区备份包-可瑞芯微工具刷机-可救砖
  • 乐观并发: TCP 与编程实践
  • 华锐视点VR风电场培训课件:多模块全面覆盖风机知识与操作​
  • UniApp 页面通讯方案全解析:从 API 到状态管理的最佳实践
  • 【Docker-Day 24】K8s网络解密:深入NodePort与LoadBalancer,让你的应用走出集群
  • B 题 碳化硅外延层厚度的确定
  • 【Linux学习笔记】信号的深入理解之软件条件产生信号
  • Docker在Windows与Linux系统安装的一体化教学设计
  • AI 基础设施新范式,百度百舸 5.0 技术深度解析
  • 【AI编程工具】快速搭建图书管理系统
  • 9.5 递归函数+常见算法
  • Preprocessing Model in MPC 7 - Matrix Triples and Convolutions Lookup Tables
  • LinuxC++项目开发日志——高并发内存池(1-定长内存池)
  • finally 与 return的执行顺序
  • Web相关知识(草稿)
  • MySQL高可用之组复制(MGR)
  • Web基础、HTTP/HTTPS协议与Nginx详解
  • 商城系统——项目测试
  • JUC的安全并发包机制
  • Python 值传递 (Pass by Value) 和引用传递 (Pass by Reference)
  • go面试题-什么是用户态和内核态
  • 数组本身的深入解析