开源框架/Jetpack

五、开源框架

1.Okhttp

Okhttp流程

  • 通过构建者构建出OkHttpClient和Request对象,再通过newCall方法获得RealCall请求对象.
  • 通过RealCall发起同步或异步请求,而决定是异步还是同步请求的是由线程分发器dispatcher来决定.
  • 当发起同步请求时会将请求加入到同步队列中依次执行,所以会阻塞UI线程,需要开启子线程执行.
  • 当发起异步请求时会创建一个线程池,并且判断请求队列是否大于最大请求队列64,请求主机数是否大于5,如果大于请求添加到异步等待队列中,否则添加到异步执行队列,并执行任务.

Okhttp 拦截器的作用是什么?

  • RetryAndFollowUpInterceptor 重试拦截器, 处理错误重试和重定向
  • BridgeInterceptor 桥接拦截器,主要工作是为请求添加cookie、添加固定的header,比如Host、Content-Length、Content-Type、User-Agent等等,然后保存响应结果的cookie,如果响应使用gzip压缩过,则还需要进行解压。
  • CacheInterceptor 缓存拦截器,如果命中缓存则不会发起网络请求。(只支持Get请求且需要配置缓存路径)
  • ConnectInterceptor 连接拦截器,内部会维护一个连接池,负责连接复用、创建连接、释放连接以及创建连接上的socket流。
  • CallServerInterceptor 请求拦截器, 进行真正的与服务器的通信,向服务器发送数据,解析读取的响应数据

addInterceptor 与 addNetworkInterceptor 的区别
应用拦截器在RetryAndFollowUpInterceptor之前,网络拦截器位于ConnectInterceptor和CallServerInterceptor之间.一旦发生错误重试或者网络重定向,网络拦截器可能执行多次,因为相当于进行了二次请求,但是应用拦截器永远只会触发一次。另外如果在CacheInterceptor中命中了缓存就不需要走网络请求了,因此会存在短路网络拦截器的情况。从使用场景看,应用拦截器因为只会调用一次,通常用于统计客户端的网络请求发起情况;而网络拦截器一次调用代表了一定会发起一次网络通信,因此通常可用于统计网络链路上传输的数据。

Okhttp 有哪些优势?

  • 支持 http2,对一台机器的所有请求共享同一个 Socket
  • 内置连接池,支持连接复用,减少延迟
  • 支持gzip 压缩响应体
  • 响应缓存可以完全避免网络重复请求
  • 请求失败时自动重试主机的其他 ip,自动重定向

Okhttp 运用了哪些设计模式?

  • 构造者模式(OkhttpClient,Request 等各种对象的创建) 工厂模式(在 Call 接口中,有一个内部工厂 Factory
    接口。)
  • 单例模式(Platform 类,已经使用 Okhttp 时使用单例)
  • 策略模式(在 CacheInterceptor 中,在响应数据的选择中使用了策略模式,选择缓存数据还是选择网络访问。)
  • 责任链模式(拦截器的链式调用)
  • 享元模式(Dispatcher 的线程池中,不限量的线程池实现了对象复用)

2.Retrofit

基本的使用

  • 通过Retrofit的builder模式创建一个retrofit对象,可以在builder里面设置okhttpclient、baseurl、callAdapterFactroy、addConverterFactory等信息。
  • 通过得到的retrofit对象加工要请求的接口,得到一个接口对象。
  • 通过这个接口对象,调用接口里面的方法得到一个网络工作对象。
  • 通过这个网络工作对象调用enqueue方法或者execute方法发起请求并且回调回请求的结果。

retrofit原理分析
通过Builder创建Retrofit对象,在create方法中,通过JDK动态代理的方式,生成实现类,在调用接口方法时,会触发InvocationHandler的invoke方法,将接口的空方法转换成ServiceMethid, 然后生成okhttp请求,通过callAdapterFactory找到对应的执行器,比如RxJava2CallAdapterFactory,最后通过ConverterFactory将返回数据解析成JavaBena,使用者只需要关心请求参数,内部实现由retrofit封装完成,底层请求还是基于okhttp实现的。

ServiceMethod
核心处理类,解析接口中定义的请求方法参数和注解,通过toCall方法将其转换成okhttp的call对象,有了Call对象,就可以发送请求了。

callFactory
字面意思就是生产Call的工厂,这里的Call是okhttp包下面的Call,CallFactory默认就是OkHttpClient

HttpUrl
就是将创建retrofit对象时传入的baseUrl转换成对象,进行格式校验等。

converterFactories
数据解析器Converter,将response通过converterFactory转换成对应的JavaBean数据形式,常见解析器有,GsonConverterFactory,FastJsonConverterFactory,当然也有xml的。

callAdapterFactories
通过calladapter将原始Call进行封装,找到对应的执行器。如rxjavaCallFactory对应的Observable,转换形式Call --> Observable

callbackExecutor
主线程执行器,返回结果在UI线程执行

Retrofit的优点
可以配置不同HTTP client来实现网络请求,如okhttp、httpclient等
将接口的定义与使用分离开来,实现结构。
支持多种返回数据解析的Converter可以快速进行数据转换。
和RxJava集成的很好
因为容易和RxJava结合使用,所以对于异步请求,同步请求也不需要做额外的工作。
Retrofit是基于OKHttp

设计模式

  • 建造者模式 (创建Retrofit对象)
  • 动态代理 (创建网络请求接口实例)
  • 工厂模式(创建callFactory)
  • 外观模式 (保存参数变量值)
  • 策略模式 (解析网络请求接口方法的参数、返回值和注解类型)
  • 装饰模式(OkhttpCall是对Okhttp中call的封装)
  • 适配器模式(CallAdapter)

3.Glide

使用

  • with:当上下文对象传入的是非全局context,如果glide在UI线程加载图片,glide底层创建出一个不可见fragment,而fragment的生命周期和activity同步,这个特殊的Fragment持有一个Lifecycle。通过Lifecycle在Fragment关键生命周期通知RequestManger进行相关的操作。在生命周期onStart时继续加载,onStop时暂停加载,onDestory是停止加载任务和清除操作。 如果传入的是全局上下文或者子线程中,那么glide加载图片跟随application的生命周期。
  • load:load方法根据传入类型不同,有多个重载,每个重载方法最后都会返回一个RequestBuilder 对象。
  • into:里边传入要显示图片的view,将处理后的图片设置到view上。传入的view在glide底层被封装成了一个target对象,target能够获取自身绑定的请求,当发现之前的请求还在的时候,会把旧的请求清除掉,绑定新的请求,这也就是为什么控件复用时不会出现图片错位的问题。设置图片之前,首先会从memorycache中读取,如果没有从磁盘读取,读取resource还是result是有磁盘缓存的策略决定的,获取到对应的图片后将图片设置给imageview。

磁盘缓存策略

  1. DiskCacheStrategy.NONE 不缓存文件
  2. DiskCacheStrategy.SOURCE 只缓存原图
  3. DiskCacheStrategy.RESULT 只缓存最终加载的图(默认的缓存略)
  4. DiskCacheStrategy.ALL 同时缓存原图和结果图

图片加载策略

  1. 活动缓存(ActivateResource),将使用的对象存放在HashMap,里面使用的弱引用,不需要时立即移除及时释放资源。当前Activity退出缓存销毁(防止有新元素添加时LRU算法把正在使用的元素回收导致找不到而崩溃)。
  2. 内存缓存:LRU内存缓存(MemoryCache),核心是使用 LinkedHashMap 实现,保存到内存中。APP应用退出缓存销毁。
  3. 磁盘缓存:使用的LRU算法进行处理,核心是使用 LinkedHashMap 实现,保存到磁盘中。(Glide使用DiskLruCache实现,将图片进行的加密、压缩处理,所以文件读写比普通IO处理效率高)
  4. 网络下载。

总结:
1、当元素在使用时,将从内存缓存(二级缓存)移动到活动缓存(一级缓存);
2、当元素未使用时,将从活动缓存释放资源,然后把该元素从活动缓存移动到内存缓存;

Glide好处体现
1、支持多种数据源,本地、网络、assets、gif等都支持。
2、生命周期集成到Glide
3、高效处理Bitmap;使用Bitmap pool复用Bitmap
4、高效缓存,支持memory和disk图片缓存
5、图片加载过程可以监听
6、可配置度高,自适应高

4.RxJava

原理
有一个泛型类,包装了Observer,即CreateEmitter类。在Observable调用subscribe传入Observer的时候,会首先把Observer用CreateEmitter包裹起来,然后当有事件发生的时候,通过这个包裹了Observer的发射器CreateEmitter发射事件,最终调用到Observer里面的相应方法。在创建被被观察者的时候,会对被观察者做一层包装, 创建几次就包装几次,然后在被观察者调用subscribe方法时,一层层回调被观察者的subscribeActual方法,而在被观察者的subscribeActual方法里,会对观察者做一层包装;
也就是说被观察者是在创建的时候进行包装,然后在subscribeActual方法里实现额外的功能;
而观察者是在被观察者调用subscribeActual方法里进行包装的,然后针对观察者实现自己额外的功能;

RxJava的线程调度
线程调度只有subscribeOn()和observeOn()两个方法。
①subscribeOn()它指示Observable在一个指定的调度器上创建(只作用于被观察者创建阶段)。只能指定一次,如果指定多次则以第一次为准
②observeOn()指定在事件传递(加工变换)和最终被处理(观察者)的发生在哪一个调度器。可指定多次,每次指定完都在下一步生效。

RXJava优点
1.链式调用代码逻辑清晰
2.操作符强大,可以实现各种功能,简化代码
3.最方便的是线程切换

RxJava的应用场景
1.网络请求处理(轮询,嵌套,出错重连)
2. 功能防抖–throttleFirst
3. 从多级缓存获取数据–concat、firstElement
4. 合并数据源–Merge
5. 联合判断–combineLatest

在这里插入图片描述在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

5.ARouter

ARouter是怎么完成 组件与组件之间通信的
第一步:注册子模块信息到路由表里面去,采用编译器APT技术,在编译的时候,扫描自定义注解,通过注解获取子模块信息,并注册到路由表里面去。
第二步:寻址操作,寻找到在编译器注册进来的子模块信息,完成交互即可。

六、Jetpack

Jetpack组件共分为四大类,Architecture(架构)、Foundation(基础)、Behavior(行为)和UI(界面)
Architecture(架构)

1.lifecycle

什么是Lifecycle
Lifecycle 是一个具备宿主生命周期感知能力的组件。它持有组件(Activity/Fragment)生命周期状态信息,并且允许其观察者监听宿主生命周期状态变化。
(1)Lifecycle(生命周期) :一个核心抽象类,用于存储有关组件(如 activity/fragment 的生命周期状态的信息,并允许其他对象观察此状态。继承该类的子类,表示本身是一个 具有Android生命周期特性 的对象。
(2)LifecycleOwner:核心接口,Lifecycle 持有者,该接口的实现类表示能够为外部提供Lifecycle实例。具有 Android 生命周期的类。这些事件可以被自定义组件用来处理生命周期的变化,而不需要在 Activity/Fragment 中实现任何代码。
(3)LifecycleRegistry:核心类,Lifecycle 的实现类,可以处理多个观察者。实现 Lifecycle 定义生命周期观察订阅,生命周期查询的方法。还实现了架构中,生命周期变化时触发的自身状态处理和相关对观察者的订阅回调的逻辑。
(4)LifecycleObserver:观察者,将一个类标记为生命周期观察者。实现该接口的类,通过注解的方式,可以通过被 LifecycleOwner 类的 addObserver() 方法注册,LifecycleObserver 便可以观察到 LifecycleOwner 的生命周期事件。
(5)State :当前生命周期所处的状态。
(6)Event :当前生命周期改变对应的事件。从框架和 Lifecycle 类分派的生命周期事件。这些事件对应到 activity/fragment 中的回调事件。

Lifecycle的使用
(1)实现LifecycleObserver
采用注解方式,使用 @OnLifecycleEvent 标记自定义的方法以实现回调。
(2)实现DefaultLifecycleObserver接口
定义一个类,实现 DefaultLifecycleObserver 接口,里面提供了完整的生命周期事件,为所有的生命周期事件都定义了对应的回调方法
(3)实现 LifecycleEventObserver,它是 LifecycleObserver 的子接口。只有一个 onStateChanged 方法,以 Lifecycle.Event 入参提供事件区分的形式,进行统一方法回调。

Lifecycle的实现原理
(1)LifecycleOwner是一个接口,它表示一个具有生命周期的组件。Activity 和 Fragment 都实现了LifecycleOwner接口。开发者可以通过实现这个接口来监听组件的生命周期变化。在创建时会创建一个Lifecycle实例。
(2)LifecycleRegistry:是一个类,它负责管理LifecycleOwner的生命周期状态,并将这些状态通知给已注册的观察者。每个LifecycleOwner都对应一个LifecycleRegistry。Lifecycle实例本质就是LifecycleRegistry,它会将自己的状态变化通知给所有注册的观察者。
(3)LifecycleObserver在收到状态变化通知后,可以根据状态变化执行相应的操作。

2.LiveData

什么是LiveData?LiveData有哪些优点?
LiveData是Android Jetpack中的一个组件,用于帮助开发者实现数据在组件之间的通信,尤其是在视图层和数据
层之间。LiveData可以感知组件的生命周期,并且在合适的时机将数据通知到观察者,从而避免了一些潜在的内存泄
漏和空指针异常等问题。
LiveData的优点包括:

  1. 生命周期感知:LiveData可以感知观察者所在的组件的生命周期状态,从而避免潜在的内存泄漏问题。
    调用 observe 方法时,会调用 owner.getLifecycle().addObserver 已达到感知生命周期的目的
  2. 数据通知:LiveData在数据更新时自动通知观察者,从而减少手动更新UI的代码量。
  3. 数据一致性:LiveData确保观察者只能接收到最新的数据,从而保证数据的一致性。

LiveData 如何感知生命周期的变化
Jetpack 引入了 Lifecycle,让任何组件都能方便地感知界面生命周期的变化。只需实现 LifecycleEventObserver 接口并注册给生命周期对象即可。
LiveData 的数据观察者在内部被包装成另一个对象(实现了 LifecycleEventObserver 接口),它同时具备了数据观察能力和生命周期观察能力。

LiveData 是如何避免内存泄漏的
LiveData 的数据观察者通常是匿名内部类,它持有界面的引用,可能造成内存泄漏。
LiveData 内部会将数据观察者进行封装,使其具备生命周期感知能力。当生命周期状态为 DESTROYED 时,自动移除观察者。

什么情况下 LiveData 会丢失数据
在高频数据更新的场景下使用 LiveData.postValue() 时,会造成数据丢失。因为“设值”和“分发值”是分开执行的,之间存在延迟。值先被缓存在变量中,再向主线程抛一个分发值的任务。若在这延迟之间再一次调用 postValue(),则变量中缓存的值被更新,之前的值在没有被分发之前就被擦除了。

粘性事件的原理
在LiveData中,如果您使用了setValue方法,那么当Observer订阅LiveData时,Observer将收到最新的更新,但是,如果在setValue调用之前已经有一个Observer订阅了LiveData,那么它将不会收到更新,这就是所谓的“粘性事件”。

LiveData的粘性事件是通过内部mLastVersion计数器来实现的。每当LiveData的setValue方法被调用时,mVersion会自增1,并将当前版本号与mLastVersion进行比较,如果当前版本号大于mLastVersion,则LiveData将通知所有的观察者,如果当前版本号小于或等于mLastVersion,则LiveData不会通知观察者。当观察者订阅LiveData时,LiveData将当前版本号分配给观察者的版本号,这样就可以确定观察者是否应该接收最新更新的数据

LiveData 粘性事件问题的解决方案
粘性:具体代码中指的是,先setValue/postValue,后调用observe(),如果成功收到了回调,即为粘性事件
(1)反射干涉Version
LiveData判断这个事件是否分发出去的关键在considerNotify方法中。
每次setValue或postValue时,mVersion会+1,只要mLastVersion>=mVersion即证明之前有过setValue或postValue。现在我们想使在observer调用前的setValue方法不被分发出去,只需要在调用observer之前的某个节点处改,变使其mLastVersion = mVersion即可。

(2)UnPeekLiveData
为每个传入的observer对象携带一个布尔类型的值,作为其是否能进入observe方法的开关。每当有一个新的observer存进来的时候,开关默认关闭。
每次setValue后,打开所有Observer的开关,允许所有observe执行。
同时方法进去后,关闭当前执行的observer开关,即不能对其第二次执行了,除非你重新setValu

setValue 和 postValue 有什么区别
简单来说:setValue 只能在主线程使用,而 postValue 不限制线程。

3.ViewModel

ViewModel 是什么
ViewModel是MVVM架构的一个层级,用来联系View和model之间的关系,以注重生命周期的方式存储和管理界面相关的数据。由于ViewModel的生命周期是作用于整个Activity的,所以就节省了一些关于状态维护的工作,最明显的就是对于屏幕旋转这种情况,以前对数据进行保存读取,而ViewModel则不需要,他可以自动保留数据。
其次,由于ViewModel在生命周期内会保持局部单例,所以可以更方便Activity的多个Fragment之间通信,因为他们能获取到同一个ViewModel实例,也就是数据状态可以共享了

ViewModel原理
Activity 的父类 ComponentActivity 实现了 ViewModelStoreOwner 接口,通过 ViewModelProvider 使用默认工厂 创建了 viewModel ,并通过唯一Key值 进行标识,存储到了 ViewModelStore 中。等下次需要的时候即可通过唯一Key值进行获取。
由于ComponentActivity 实现了ViewModelStoreOwner 接口,实现了 getViewModelStore 方法,当屏幕旋转的时候,会先调用
onRetainNonConfigurationInstance() 方法将 viewModelStore 保存起来,然后再调用 getLastNonConfigurationInstance 方法将数据恢复,如果为空的话,会重新创建 viewModelStore ,并存储在全局中,以便以下次发生变化的时候,能够通过onRetainNonConfigurationInstance 保存起来。
最后当页面销毁并且没有配置更改的时候,会将viewModelStore 中的数据 进行清除操作

4.DataBinding

5.MVVM

MVC、MVP、MVVM
1.MVC:
M——模型层(Model)负责处理数据的加载或者存储
V——视图层(View)负责界面数据的展示,与用户进行交互
C——控制器层(Controller)负责逻辑业务的处理
在MVC模式中,View层可以直接访问Model层和Controller层,所以View层包含Model层信息和Controller层的业务逻辑处理。
缺点:
Activity和Fragment既有View的性质,又具有Controller的性质,导致Acyivity和Fragment很重
MVC中View层与Model层直接交互,所以Activity和Fragment与Model的耦合性很高
2.MVP:
M——数据层(Model)负责对数据的存取操作,例如对数据库的读写,网络的数据的请求等
V——视图层(View)负责对数据的展示,提供友好的界面与用户进行交互,Android通常将Activity或者Fragment作为View层
P——控制器层(Presenter)连接View层与Model层的桥梁并对业务逻辑进行处理
MVP执行流程:
View层收到用户的操作
View层把用户的操作交给Presenter
Presenter直接操作Model层进行业务逻辑处理
Model层处理完毕后,通知Presenter
Presenter收到通知后,去更新View层
优点:
模型与视图完全分离,修改View而不Model
可以更高效的使用Model,所有的交互都发生在——Presenter内部
将一个Presenter用于多个视图,而不需要改变Presenter的逻辑,View变化比Model变化频繁
逻辑结构清晰,View层代码不再臃肿
缺点:
MVP模式基于接口设计,会增加很多类,代码逻辑虽然清晰,但代码量庞大。
不能复用
3.MVVM:
M——Model(模型)实体模型,定义实体类,获取业务数据模型,如通过数据库或者网络来操作数据等
V——View(视图)布局文件(XML),主要进行控件的初始化设置
VM——ViewModel(控制器):连接 View 与 Model 的中间桥梁,ViewModel 与 Model 直接交互,将数据变化反应给View。
优点:
结构清晰,职责划分清晰
模块间充分解耦
在 MVP 的基础上,MVVM 把 View 和 ViewModel 也进行了解耦
数据复用(ViewModel 层对数据的获取和处理逻辑是可以复用的)

6.Room

7.Navigation

8.Paging

  • 8
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值