- 前台
Activity
:活跃的Activity
,正在和用户交互的Activity
。 - 可见但非前台的
Activity
:常见于栈顶的Activity
背景透明,处在其下面的Activity
就是可见但是不可和用户交互。 - 后台
Activity
:已经被暂停的Activity
,比如已经执行了onStop
方法。
所以,onStart
和onStop
通常指的是当前活动是否位于前台这个角度,而onResume
和onPause
从是否可见这个角度来讲的。
2. 屏幕适配
平时如何有使用屏幕适配吗?原理是什么呢?
平时的屏幕适配一般采用的头条的屏幕适配方案。简单来说,以屏幕的一边作为适配,通常是宽。
原理:设备像素px
和设备独立像素dp
之间的关系是
px = dp * density
假设UI给的设计图屏幕宽度基于360dp,那么设备宽的像素点已知,即px,dp也已知,360dp,所以density = px / dp
,之后根据这个修改系统中跟density
相关的知识点即可。
3. Android消息机制
Android消息机制介绍?
Android消息机制中的四大概念:
ThreadLocal
:当前线程存储的数据仅能从当前线程取出。MessageQueue
:具有时间优先级的消息队列。Looper
:轮询消息队列,看是否有新的消息到来。Handler
:具体处理逻辑的地方。
过程:
- 准备工作:创建
Handler
,如果是在子线程中创建,还需要调用Looper#prepare()
,在Handler
的构造函数中,会绑定其中的Looper
和MessageQueue
。 - 发送消息:创建消息,使用
Handler
发送。 - 进入
MessageQueue
:因为Handler
中绑定着消息队列,所以Message
很自然的被放进消息队列。 Looper
轮询消息队列:Looper
是一个死循环,一直观察有没有新的消息到来,之后从Message
取出绑定的Handler
,最后调用Handler
中的处理逻辑,这一切都发生在Looper
循环的线程,这也是Handler
能够在指定线程处理任务的原因。
Looper在主线程中死循环为什么没有导致界面的卡死?
- 导致卡死的是在Ui线程中执行耗时操作导致界面出现掉帧,甚至
ANR
,Looper.loop()
这个操作本身不会导致这个情况。 - 有人可能会说,我在点击事件中设置死循环会导致界面卡死,同样都是死循环,不都一样的吗?Looper会在没有消息的时候阻塞当前线程,释放CPU资源,等到有消息到来的时候,再唤醒主线程。
- App进程中是需要死循环的,如果循环结束的话,App进程就结束了。
建议阅读:
IdleHandler介绍?
介绍:
IdleHandler是在Hanlder空闲时处理空闲任务的一种机制。
执行场景:
MessageQueue
没有消息,队列为空的时候。MessageQueue
属于延迟消息,当前没有消息执行的时候。
会不会发生死循环:
答案是否定的,MessageQueue
使用计数的方法保证一次调用MessageQueue#next
方法只会使用一次的IdleHandler
集合。
4. View事件分发机制和View绘制原理
刚哥的《Android开发艺术探索》已经很全面了,建议阅读。
5. Bitmap
Bitmap的内存计算方式?
在已知图片的长和宽的像素的情况下,影响内存大小的因素会有资源文件位置和像素点大小。
像素点大小:
常见的像素点有:
- ARGB_8888:4个字节
- ARGB_4444、ARGB_565:2个字节
资源文件位置:
不同dpi对应存放的文件夹
比如一个一张图片的像素为180*180px
,dpi
(设备独立像素密度)为320,如果它仅仅存放在drawable-hdpi
,则有:
横向像素点 = 180 * 320/240 + 0.5f = 240 px
纵向像素点 = 180 * 320/240 + 0.5f = 240 px
如果
如果它仅仅存放在drawable-xxhdpi
,则有:
横向像素点 = 180 * 320/480 + 0.5f = 120 px
纵向像素点 = 180 * 320/480 + 0.5f = 120 px
所以,对于一张180*180px
的图片,设备dpi为320,资源图片仅仅存在drawable-hdpi
,像素点大小为ARGB_4444
,最后生成的文件内存大小为:
横向像素点 = 180 * 320/240 + 0.5f = 240 px
纵向像素点 = 180 * 320/240 + 0.5f = 240 px
内存大小 = 240 * 240 * 2 = 115200byte 约等于 112.5kb
建议阅读:
Bitmap的高效加载?
Bitmap的高效加载在Glide中也用到了,思路:
- 获取需要的长和宽,一般获取控件的长和宽。
- 设置
BitmapFactory.Options
中的inJustDecodeBounds
为true,可以帮助我们在不加载进内存的方式获得Bitmap
的长和宽。 - 对需要的长和宽和Bitmap的长和宽进行对比,从而获得压缩比例,放入
BitmapFactory.Options
中的inSampleSize
属性。 - 设置
BitmapFactory.Options
中的inJustDecodeBounds
为false,将图片加载进内存,进而设置到控件中。
二、Android进阶
Android进阶中重点考察Android Framework
、性能优化和第三方框架。
1. Binder
Binder的介绍?与其他IPC方式的优缺点?
Binder是Android中特有的IPC方式,引用《Android开发艺术探索》中的话(略有改动):
从IPC角度来说,Binder是Android中的一种跨进程通信方式;Binder还可以理解为虚拟的物理设备,它的设备驱动是/dev/binder;从
Android Framework
来讲,Binder是Service Manager
连接各种Manager
和对应的ManagerService
的桥梁。从面向对象和CS模型来讲,Client
通过Binder和远程的Server
进行通讯。
基于Binder,Android还实现了其他的IPC方式,比如AIDL
、Messenger
和ContentProvider
。
与其他IPC比较:
- 效率高:除了内存共享外,其他IPC都需要进行两次数据拷贝,而因为Binder使用内存映射的关系,仅需要一次数据拷贝。
- 安全性好:接收方可以从数据包中获取发送发的进程Id和用户Id,方便验证发送方的身份,其他IPC想要实验只能够主动存入,但是这有可能在发送的过程中被修改。
Binder的通信过程?Binder的原理?
图片:
其实这个过程也可以从AIDL生成的代码中看出。
原理:
Binder的结构:
Client
:服务的请求方。
Server
:服务的提供方。
Service Manager
:为Server
提供Binder
的注册服务,为Client
提供Binder
的查询服务,Server
、Client
和Service Manage
r的通讯都是通过Binder。
Binder驱动
:负责Binder通信机制的建立,提供一系列底层支持。
从上图中,Binder通信的过程是这样的:
- Server在Service Manager中注册:Server进程在创建的时候,也会创建对应的Binder实体,如果要提供服务给Client,就必须为Binder实体注册一个名字。
- Client通过Service Manager获取服务:Client知道服务中Binder实体的名字后,通过名字从Service Manager获取Binder实体的引用。
- Client使用服务与Server进行通信:Client通过调用Binder实体与Server进行通信。
更详细一点?
Binder通信的实质是利用内存映射,将用户进程的内存地址和内核的内存地址映射为同一块物理地址,也就是说他们使用的同一块物理空间,每次创建Binder的时候大概分配128的空间。数据进行传输的时候,从这个内存空间分配一点,用完了再释放即可。
2. 序列化
Android有哪些序列化方式?
为了解决Android中内存序列化速度过慢的问题,Android使用了Parcelable
。
对比 | Serializable | Parcelable |
---|---|---|
易用性 | 简单 | 不是很简单 |
效率 | 低 | 高 |
场景 | IO、网络和数据库 | 内存中 |
3. Framework
Zygote孕育进程过程?
Activity的启动过程?
建议阅读:
App的启动过程?
介绍一下App进程和System Server进程如何联系:
ActivityThread
:依赖于Ui线程,实际处理与AMS
中交互的工作。ActivityManagerService
:负责Activity
、Service
等的生命周期工作。ApplicationThread
:System Server
进程中ApplicatonThreadProxy
的服务端,帮助System Server
进程跟App进程交流。System Server
:Android核心的进程,掌管着Android系统中各种重要的服务。
具体过程:
- 用户点击App图标,
Lanuacher
进程通过Binder
联系到System Server
进程发起startActivity
。 System Server
通过Socket
联系到Zygote
,fork
出一个新的App进程。- 创建出一个新的App进程以后,
Zygote
启动App进程的ActivityThread#main()
方法。 - 在
ActivtiyThread
中,调用AMS
进行ApplicationThread
的绑定。 AMS
发送创建Application
的消息给ApplicationThread
,进而转交给ActivityThread
中的H
,它是一个Handler
,接着进行Application
的创建工作。AMS
以同样的方式创建Activity
,接着就是大家熟悉的创建Activity
的工作了。
Apk的安装过程?
建议阅读:
Activity启动过程跟Window的关系?
建议阅读:
Activity、Window、ViewRoot和DecorView之间的关系?
建议阅读:
4. Context
关于Context的理解?
建议阅读:
5. 断点续传
多线程断点续传?
基础知识:
- Http基础:在Http请求中,可以加入请求头
Range
,下载指定区间的文件数。 RandomAccessFile
:支持随机访问,可以从指定位置进行数据的读写。
有了这个基础以后,思路就清晰了:
- 通过
HttpUrlConnection
获取文件长度。 - 自己分配好线程进行制定区间的文件数据的下载。
- 获取到数据流以后,使用
RandomAccessFile
进行指定位置的读写。
6. 性能优化
平时做了哪些性能优化?
建议阅读:
7. 第三方库
一定要在熟练使用后再去查看原理。
Glide
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)
结尾
最后小编想说:不论以后选择什么方向发展,目前重要的是把Android方面的技术学好,毕竟其实对于程序员来说,要学习的知识内容、技术有太多太多,要想不被环境淘汰就只有不断提升自己,从来都是我们去适应环境,而不是环境来适应我们!
当程序员容易,当一个优秀的程序员是需要不断学习的,从初级程序员到高级程序员,从初级架构师到资深架构师,或者走向管理,从技术经理到技术总监,每个阶段都需要掌握不同的能力。早早确定自己的职业方向,才能在工作和能力提升中甩开同龄人。
想要拿高薪实现技术提升薪水得到质的飞跃。最快捷的方式,就是有人可以带着你一起分析,这样学习起来最为高效,所以为了大家能够顺利进阶中高级、架构师,我特地为大家准备了一套高手学习的源码和框架视频等精品Android架构师教程,保证你学了以后保证薪资上升一个台阶。
当你有了学习线路,学习哪些内容,也知道以后的路怎么走了,理论看多了总要实践的。
高级UI,自定义View
UI这块知识是现今使用者最多的。当年火爆一时的Android入门培训,学会这小块知识就能随便找到不错的工作了。
不过很显然现在远远不够了,拒绝无休止的CV,亲自去项目实战,读源码,研究原理吧!
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
(img-LGUkXO0e-1712427051736)]
高级UI,自定义View
UI这块知识是现今使用者最多的。当年火爆一时的Android入门培训,学会这小块知识就能随便找到不错的工作了。
不过很显然现在远远不够了,拒绝无休止的CV,亲自去项目实战,读源码,研究原理吧!
[外链图片转存中…(img-iXjgxbo0-1712427051736)]
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!