Thank you for your support :)
CC BY 4.0 (Attribution 4.0 International)
写在前面——本文将持续更新我在学习Android开发过程中遇到的相关知识点汇总,希望自己可以在不断的反思过程中得到提高,同时也感谢所有人给我提供的帮助。
RecycleView
A flexible view for providing a limited window into a large data set.
学习链接
组成
RecyclerView的四大组成是:
- Layout Manager:Item的布局。
- Adapter:为Item提供数据。
- Item Decoration:Item之间的Divider。
- Item Animator:添加、删除Item动画。
布局管理器
RecyclerView提供了三种布局管理器:
- LinerLayoutManager 以垂直或者水平列表方式展示Item。
- GridLayoutManager 以网格方式展示Item。
- StaggeredGridLayoutManager 以瀑布流方式展示Item。
常见API
canScrollHorizontally();//能否横向滚动
canScrollVertically();//能否纵向滚动
scrollToPosition(int position);//滚动到指定位置
setOrientation(int orientation);//设置滚动的方向
getOrientation();//获取滚动方向
findViewByPosition(int position);//获取指定位置的Item View
findFirstCompletelyVisibleItemPosition();//获取第一个完全可见的Item位置
findFirstVisibleItemPosition();//获取第一个可见Item的位置
findLastCompletelyVisibleItemPosition();//获取最后一个完全可见的Item位置
findLastVisibleItemPosition();//获取最后一个可见Item的位置
缓存机制
离屏的ItemView即被回收至缓存,入屏的ItemView则会优先从缓存中获取。
ListView和RecyclerView缓存机制基本一致:
mActiveViews和mAttachedScrap功能相似,意义在于快速重用屏幕上可见的列表项ItemView,而不需要重新createView和bindView;
mScrapView和mCachedViews + mReyclerViewPool功能相似,意义在于缓存离开屏幕的ItemView,目的是让即将进入屏幕的ItemView重用.
RecyclerView的优势在于
- mCacheViews的使用,可以做到屏幕外的列表项ItemView进入屏幕内时也无须bindView快速重用;
- mRecyclerPool可以供多个RecyclerView共同使用,在特定场景下,如viewpaper+多个列表页下有优势。
客观来说,RecyclerView在特定场景下对ListView的缓存机制做了补强和完善。
回收机制
RecyclerView和ListView的回收机制非常相似,但是ListView是以View作为单位进行回收,RecyclerView是以ViewHolder作为单位进行回收。 Recycler是RecyclerView回收机制的实现类,他实现了四级缓存:
- mAttachedScrap: 缓存在屏幕上的ViewHolder。
- mCachedViews: 缓存屏幕外的ViewHolder,默认为2个。ListView对于屏幕外的缓存都会调用
getView()
。 - mViewCacheExtensions: 需要用户定制,默认不实现。
- mRecyclerPool: 缓存池,多个RecyclerView共用。
结论
- 在一些场景下,如界面初始化,滑动等,ListView和RecyclerView都能很好地工作,两者并没有很大的差异:
- 数据源频繁更新的场景,RecyclerView的优势会非常明显;
进一步来讲,结论是: 列表页展示界面,需要支持动画,或者频繁更新,局部刷新,建议使用RecyclerView,更加强大完善,易扩展;其它情况(如微信卡包列表页)两者都OK,但ListView在使用上会更加方便,快捷。
Retrofit
A type-safe HTTP client for Android and Java.
学习链接
组成
Retrofit是由Square公司开发的一个开源的高质量高效率的HTTP库,是一个可以简化我们网络操作的工作的第三方库。它将我们自己开发的底层的代码和细节都封装了起来,有了Retrofit之后我们对于一些请求我们就只需要一行代码或者一个注解。所有的网络通信,其核心任务就只有一个就是: Client端与Server端进行数据和交互操作,所有Retrofit就将底层代码都封装起来,只是暴露除了我们业务中的数据模型和操作方法。下图是Retrofit的配置:
注解详解
1、方法注解:@GET
@POST
、@PUT
、@DELETE
、@PATCH
、@OPTIONS
、@HTTP
2、标记注解:@FormUrlEncoded
、@Multipart
、@Streaming
3、参数注解:@Query
、@QueryMap
、@Body
、@Field
、@FieldMap
、@Part
、@PartMap
4、其它注解:@Path
、@Header
、@Headers
、@Url
结论
Retrofit将REST API抽象成Java接口,使用注解来描述每一个API地址和请求,支持URL参数替换(包括查询参数和路径参数),以及表单编码和多部分请求功能。
Android异步通信
学习链接
定义
Android的异步通信机制就是一套消息传递机制。
作用
在多线程的应用场景中,将工作线程中需更新UI
的操作信息 传递到 UI
主线程,从而实现 工作线程对UI
的更新处理,最终实现异步消息的处理。
为什么要用Handler
消息传递机制
多个线程并发更新UI的同时 保证线程安全,具体描述如下:
相关概念
关于 Handler
机制中的相关概念如下:
在下面的讲解中,我将直接使用英文名讲解,即
Handler
、Message
、Message Queue
、Looper
,希望大家先熟悉相关概念
工作原理解析
下面,我将定性地讲解Handler
机制的工作流程
工作流程解析
Handler
机制的工作流程主要包括4个步骤:
- 异步通信准备
- 消息发送
- 消息循环
- 消息处理
具体如下图:
工作流程图
示意图
特别注意
线程(Thread)
、循环器(Looper)
、处理者(Handler)
之间的对应关系如下:
- 1个线程
(Thread)
只能绑定 1个循环器(Looper)
,但可以有多个处理者(Handler)
- 1个循环器
(Looper)
可绑定多个处理者(Handler)
- 1个处理者
(Handler)
只能绑定1个1个循环器(Looper)
同步屏障
当设置了同步屏障之后,next函数将会忽略所有的同步消息,返回异步消息。换句话说就是,设置了同步屏障之后,Handler只会处理异步消息。再换句话说,同步屏障为Handler消息机制增加了一种简单的优先级机制,异步消息的优先级要高于同步消息。
Android事件分发机制
学习链接
Activity的事件分发机制
ViewGroup事件的分发机制
View事件的分发机制
自定义View
学习链接
自定义View基础 - 最易懂的自定义View原理系列(1)
自定义View Measure过程 - 最易懂的自定义View原理系列(2)
自定义View Layout过程 - 最易懂的自定义View原理系列(3)
自定义View Draw过程- 最易懂的自定义View原理系列(4)
目录大纲
分类
类型 | 定义 |
---|---|
自定义组合控件 | 多个空间组合为一个新的控件,方便多处复用 |
继承系统View控件 | 继承自TextView等系统控件,在系统控件的基础功能上进行扩展 |
继承View | 不复用系统控件逻辑,继承View进行功能定义 |
继承系统ViewGroup | 继承自LinearLayout等系统控件,在系统控件的基础功能上进行扩展 |
继承ViewViewGroup | 不复用系统控件逻辑,继承ViewGroup进行功能定义 |
1.自定义View基础
2.自定义View Measure过程
3.自定义View Layout过程
4.自定义View Draw过程
Binder
学习链接
Binder的定义
- 中文即 粘合剂,意思为粘合了两个不同的进程
- 网上有很多对
Binder
的定义,但都说不清楚:Binder
是跨进程通信方式、它实现了IBinder
接口,是连接ServiceManager
的桥梁blabla,估计大家都看晕了,没法很好的理解 - 我认为:对于
Binder
的定义,在不同场景下其定义不同
在本文的讲解中,按照 大角度 -> 小角度 去分析Binder
,即:
- 先从 机制、模型的角度 去分析 整个
Binder
跨进程通信机制的模型
其中,会详细分析模型组成中的
Binder
驱动
- 再 从源码实现角度,分析
Binder
在Android
中的具体实现
从而全方位地介绍 Binder
,希望你们会喜欢。
跨进程通信机制 原理
进程空间划分
- 一个进程空间分为 用户空间 & 内核空间(
Kernel
),即把进程内 用户 & 内核 隔离开来 - 二者区别:
- 进程间,用户空间的数据不可共享,所以用户空间 = 不可共享空间
- 进程间,内核空间的数据可共享,所以内核空间 = 可共享空间
所有进程共用1个内核空间
- 进程内 用户空间 & 内核空间 进行交互 需通过 系统调用,主要通过函数:
- copy_from_user():将用户空间的数据拷贝到内核空间
- copy_to_user():将内核空间的数据拷贝到用户空间
进程隔离 & 跨进程通信(IPC )
- 进程隔离 为了保证 安全性 & 独立性,一个进程 不能直接操作或者访问另一个进程,即
Android
的进程是相互独立、隔离的 - 跨进程通信(
IPC
) 即进程间需进行数据交互、通信 - 跨进程通信的基本原理
a. 而Binder
的作用则是:连接 两个进程,实现了mmap()系统调用,主要负责 创建数据接收的缓存空间 & 管理数据接收缓存 b. 传统的跨进程通信需拷贝数据2次,但Binder
机制只需1次,主要是使用到了内存映射,具体下面会详细说明
Binder跨进程通信机制 模型
模型原理图
Binder
跨进程通信机制 模型 基于 Client - Server
模式:
模型组成角色说明
梳理Binder的核心原理
模型原理步骤说明
额外说明
说明1
Client
进程、Server
进程 & Service Manager
进程之间的交互 都必须通过Binder
驱动(使用 open
和 ioctl
文件操作函数),而非直接交互
原因:
Client
进程、Server
进程 &Service Manager
进程属于进程空间的用户空间,不可进行进程间交互Binder
驱动 属于 进程空间的 内核空间,可进行进程间 & 进程内交互
所以,原理图可表示为以下:
虚线表示并非直接交互
说明2
Binder
驱动 & Service Manager
进程 属于 Android
基础架构(即系统已经实现好了),而Client
进程 和 Server
进程 属于Android
应用层(需要开发者自己实现)
所以,在进行跨进程通信时,开发者只需自定义Client
& Server
进程 并 显式使用上述3个步骤,最终借助 Android
的基本架构功能就可完成进程间通信
说明3
Binder请求的线程管理
Server
进程会创建很多线程来处理Binder
请求Binder
模型的线程管理 采用Binder
驱动的线程池,并由Binder
驱动自身进行管理
而不是由
Server
进程来管理的
- 一个进程的
Binder
线程数默认最大是16,超过的请求会被阻塞等待空闲的Binder线程。
所以,在进程间通信时处理并发问题时,如使用
ContentProvider
时,它的CRUD
(创建、检索、更新和删除)方法只能同时有16个线程同时工作
- 至此,我相信大家对
Binder
跨进程通信机制 模型 已经有了一个非常清晰的定性认识 - 下面,我将通过一个实例,分析
Binder
跨进程通信机制 模型在Android
中的具体代码实现方式
即分析 上述步骤在
Android
中具体是用代码如何实现的
Binder机制 在Android中的具体实现原理
Binder
机制在Android
中的实现主要依靠Binder
类,其实现了IBinder
接口
下面会详细说明
- 实例说明:
Client
进程 需要调用Server
进程的加法函数(将整数a和b相加)
即:
Client
进程 需要传两个整数给Server
进程Server
进程 需要把相加后的结果 返回给Client
进程
- 具体步骤 下面,我会根据
Binder
跨进程通信机制 模型的步骤进行分析
步骤1:注册服务
- 过程描述
Server
进程 通过Binder
驱动 向Service Manager
进程 注册服务 - 代码实现
Server
进程 创建 一个Binder
对象
Binder
实体是Server
进程 在Binder
驱动中的存在形式- 该对象保存
Server
和ServiceManager
的信息(保存在内核空间中)Binder
驱动通过 内核空间的Binder
实体 找到用户空间的Server
对象
注册服务后,Binder
驱动持有 Server
进程创建的Binder
实体
步骤2:获取服务
Client
进程 使用 某个service
前(此处是 相加函数),须 通过Binder
驱动 向ServiceManager
进程 获取相应的Service
信息- 具体代码实现过程如下:
此时,Client
进程与 Server
进程已经建立了连接
步骤3:使用服务
Client
进程 根据获取到的 Service
信息(Binder
代理对象),通过Binder
驱动 建立与 该Service
所在Server
进程通信的链路,并开始使用服务
- 过程描述
Client
进程 将参数(整数a和b)发送到Server
进程Server
进程 根据Client
进程要求调用 目标方法(即加法函数)Server
进程 将目标方法的结果(即加法后的结果)返回给Client
进程
结论
对比 Linux
(Android
基于Linux
)上的其他进程通信方式(管道、消息队列、共享内存、 信号量、Socket
),Binder
机制的优点有:
Picasso
学习链接
Picasso是Android开发中的经典图片加载框架,可以实现如下功能:
- 处理Adapter 中ImageView的回收和取消下载。
- 使用最小的内存 来做复杂的图片变换。比如高斯模糊,圆角、圆形等处理。
- 自动帮我们缓存图片。内存和磁盘缓存。