launch {

println(“launch1 ${Thread.currentThread().name}”)

delay(1000)

println(“launch1 finished”)

}

launch {

println(“launch2 ${Thread.currentThread().name}”)

delay(1000)

println(“launch2 finished”)

}

}

}

这里的launch函数和刚才的GlobalScope.launch不一样,这个launch只能在协程的作用域下面调用,且会创建一个子协程.子协程的特点是如果外层作用域的协程结束了,那么该作用域下的所有子协程也会一同结束.

上面的输出如下:

launch1 main

launch2 main

launch1 finished

launch2 finished

日志是交叉打印的,很明显,这是并发执行的.但是线程却是相同的线程.这里由编程语言来决定如何在多个协程之间进行调度,让谁挂起,让谁运行.调度过程不需要操作系统参与,这使得协程并发效率出奇得高.

9.3 suspend 挂起

当需要将部分代码提取到一个单独的函数中,这个函数是没有协程作用域的.Kotlin提供一个suspend关键字,使用它可以将任意函数声明成挂起函数,挂起函数之间是可以互相调用的.

suspend只能声明挂起函数,而不能提供协程作用域,在里面调用launch(必须在协程作用域调用才行)是不得行的.要想有协程作用域,可以使用coroutineScope.

coroutineScope也是一个挂起函数,因此可以在其他任何挂起函数中调用.coroutineScope会继承外部的协程作用域并创建一个子作用域. 于是可以这样用:

suspend fun printDot() {

coroutineScope {

launch {

println(“.”)

delay(1000)

println(“延迟之后的输出”)

}

}

}

coroutineScope有点类似runBlocking,保证其作用域内的所有代码和子线程全部执行完之前,会一直阻塞当前协程.

但是runBlocking会阻塞当前线程,影响较大.而coroutineScope只会阻塞当前协程,不会影响其他协程,也不会影响其他线程.

可创建新的协程作用域:

  • GlobalScope.launch 可在任何地方调用

  • runBlocking 可在任何地方调用

  • lanuch

  • coruotineScope

9.4 更多的作用域构建器

runBlocking会阻塞线程,只能在测试环境下使用.而GlobalScope.launch是顶层协程,比如在Activity中使用来请求网络,还没请求回来的时候,Activity已关闭,这时需要手动管理(去取消)这个顶层协程,比较麻烦. 调用下面的代码会取消顶层协程.

val job = GlobalScope.launch { }

job.cancel()

但是实际项目中,一般会用CoroutineScope

val job = Job()

//返回的是CoroutineScope对象 这里是调用的CoroutineScope方法

val scope = CoroutineScope(job)

scope.launch {

}

所有使用CoroutineScope对象的launch创建的协程统统会被job所管理(都是在它的作用域下面).大大降低协程维护成本.

9.5 创建协程,并获取其执行结果

使用async函数,就可以获取协程的执行结果.它会创建一个子协程,并返回Deferred对象,然后我们调用其await方法即可知道结果.下面是简单计算一下5+5

runBlocking {

val result = async {

delay(100)

5 + 5

}.await()

println(result)

}

注意,调用await方法之后会阻塞当前协程,直到子协程拿到结果,才会执行后面的代码(对应上面是println语句).为了提高效率,可以先拿到返回Deferred对象,最后需要结果的时候才调用await方法

runBlocking {

val start = System.currentTimeMillis()

val deferred1 = async {

delay(1000)

5 + 5

}

val deferred2 = async {

delay(1000)

6 + 6

}

println(“结果是 ${deferred1.await() + deferred2.await()}”)

val end = System.currentTimeMillis()

println(“花费时间: ${end - start}”)

}

9.6 withContext

withContext大致是async函数的简化版,它是一个挂起函数,返回结果是withContext函数体内最后一行代码.相当于val result = async{5+5}.await()

runBlocking {

val result = withContext(Dispatchers.Default) {

5 + 5

}

println(result)

}

调用withContext函数后,函数体内的代码会被立即执行,同时需要指定一个线程参数.这个参数有如下几个值:

  • Dispatchers.Default 会开启子线程,并使用一种较低并发的线程策略.适合计算密集型任务.

  • Dispatchers.IO 会开启子线程,并使用一种较高并发的线程策略.网络请求比较合适

  • Dispatchers.Main 不会开启子线程,而是在Android主线程执行代码.

9.7 使用协程简化回调

suspendCoroutine 函数可以将当前协程立即挂起,然后在一个普通的线程执行lambda表达式中的代码.Lambda表达式的参数是一个Continuation参数,调用它的resume方法或resumeWithException可以让协程恢复执行.

来看一段代码:

suspend fun request(address: String): String {

return suspendCoroutine { continuation ->

HttpUtil.sendHttpRequest(address, object : HttpCallbackListener {

override fun onFinish(response: String) {

continuation.resume(response)

}

override fun onError(e: Exception) {

continuation.resumeWithException(e)

}

})

}

}

GlobalScope.launch {

val response = request(“https://www.baidu.com/”)

Log.d(“xfhy”, “网络请求结果 : $response”)

}

将网络请求的代码用suspendCoroutine包装一下,免得每次去手动生成一个匿名类,然后在里面拿到结果的时候调用continuation的resume方法将结果返回,这样在外面即可拿到结果. 使用request方法请求网络,只需要写一句代码即可.上面为了实例,没有加try…catch.

10. Android系统架构


JK14sg.png

Linux内核

Android平台的基础是Linux内核.

硬件抽象层(HAL)

硬件抽象层提供标准界面,向更高级别的Java API框架显示设备硬件功能.

Android Runtime

对于运行Android 5.0(API 21) 或更高版本的设备,每个应用都在棋自己的进程中运行,并且有其自己的Android Runtime(ART)实例.

原生C/C++库

许多核心Android系统组件和服务(例如ART和HAL)构建自原生代码,需要以C和C++编写的原生库.

Java API 框架

可通过以Java语言编写的API使用Android OS 的整个功能集.

系统应用

Android随附一套用于电子邮件,短信,日历,互联网浏览和联系人等的核心应用.

11. Jetpack


Jetpack是一个开发者组件工具集,主要目的是帮助我们写出更加简洁的代码,简化开发过程.Jetpack中的组件,大部分不依赖任何Android系统版本,这些组件通常定义在AndroidX库中,并且拥有非常好的向下兼容性.

Jetpack官网地址

11.1 ViewModel

ViewModel官网地址

ViewModel是用来专门存放于界面相关数据的,尽量将数据存放到ViewModel中,减少Activity的逻辑. ViewModel 类旨在以注重生命周期的方式存储和管理界面相关的数据。ViewModel 类让数据可在发生屏幕旋转等配置更改后继续存在。下面是ViewModel的生命周期

ViewModel 使用及原理解析

11.2 Lifecycles

让任何类都能轻松感知到Activity的生命周期.

Lifecycle 使用及原理解析 一文搞懂

11.3 LiveData

LiveData是Jetpack提供的一种响应式编程组件,它可以包含任何类型的数据,并在数据发生变化的时候通知给观察者. LiveData是Activity与ViewModel之间通信的桥梁,它内部靠的是Lifecycles组件来自我感知生命周期的变化,从而在Activity销毁的时候及时释放引用,避免产生内存泄露.

LiveData 使用及原理解析

11.4 Room

Android官网的ORM框架(对象关系映射).

11.4.1 Entity

定义封装实际数据的实体类,每个视图类都会在数据库中有一张对应的表,并且表中的列是根据实体类中的字段自动生成的.

11.4.2 Dao

数据访问对象,通常会在这里对数据库的各项操作进行封装.

11.4.3 Database

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
img

架构师筑基包括哪些内容

我花了将近半个月时间将:深入 Java 泛型.、注解深入浅出、并发编程.、数据传输与序列化、Java 虚拟机原理、反射与类加载、高效 IO、Kotlin项目实战等等Android架构师筑基必备技能整合成了一套系统知识笔记PDF,相信看完这份文档,你将会对这些Android架构师筑基必备技能有着更深入、更系统的理解。

由于文档内容过多,为了避免影响到大家的阅读体验,在此只以截图展示部分内容

注:资料与上面思维导图一起看会更容易学习哦!每个点每个细节分支,都有对应的目录内容与知识点!



这份资料就包含了所有Android初级架构师所需的所有知识!

本文已被CODING开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》收录

一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!

AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算

都有对应的目录内容与知识点!**

[外链图片转存中…(img-MgZaBsNO-1712478027113)]
[外链图片转存中…(img-2yJDlQKO-1712478027113)]
这份资料就包含了所有Android初级架构师所需的所有知识!

本文已被CODING开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》收录

一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!

AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐