Android第三方庫(kù)解析
前言
很多人面試之前,可能沒有在互聯(lián)網(wǎng)公司工作過或者說工作過但年頭較短,不知道互聯(lián)網(wǎng)公司技術(shù)面試都會(huì)問哪些問題? 再加上可能自己準(zhǔn)備也不充分,去面試沒幾個(gè)回合就被面試官幾個(gè)問題打蒙了,最后以慘敗收?qǐng)觥?/p>
1.Retrofit網(wǎng)絡(luò)請(qǐng)求框架
概念:Retrofit是一個(gè)基于RESTful的HTTP網(wǎng)絡(luò)請(qǐng)求框架的封裝,其中網(wǎng)絡(luò)請(qǐng)求的本質(zhì)是由OKHttp完成的,而Retrofit僅僅負(fù)責(zé)網(wǎng)絡(luò)請(qǐng)求接口的封裝。
原理:App應(yīng)用程序通過Retrofit請(qǐng)求網(wǎng)絡(luò),實(shí)際上是使用Retrofit接口層封裝請(qǐng)求參數(shù),Header、URL等信息,之后由OKHttp完成后續(xù)的請(qǐng)求,在服務(wù)器返回?cái)?shù)據(jù)之后,OKHttp將原始的結(jié)果交給Retrofit,最后根據(jù)用戶的需求對(duì)結(jié)果進(jìn)行解析。
retrofit使用
1.在retrofit中通過一個(gè)接口作為http請(qǐng)求的api接口
public interface NetApi { @GET("repos/{owner}/{repo}/contributors") Call contributorsBySimpleGetCall(@Path("owner") String owner, @Path("repo") String repo);}
2.創(chuàng)建一個(gè)Retrofit實(shí)例
Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://api.github.com/") .build();
3.調(diào)用api接口
- NetApi repo = retrofit.create(NetApi.class);
- //第三步:調(diào)用網(wǎng)絡(luò)請(qǐng)求的接口獲取網(wǎng)絡(luò)請(qǐng)求
- retrofit2.Call<ResponseBody> call = repo.contributorsBySimpleGetCall("username", "path");
- call.enqueue(new Callback<ResponseBody>() { //進(jìn)行異步請(qǐng)求
- @Override
- public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
- //進(jìn)行異步操作
- }
- @Override
- public void onFailure(Call<ResponseBody> call, Throwable t) {
- //執(zhí)行錯(cuò)誤回調(diào)方法
- }
- });
retrofit動(dòng)態(tài)代理
retrofit執(zhí)行的原理如下:
- 首先,通過method把它轉(zhuǎn)換成ServiceMethod。
- 然后,通過serviceMethod,args獲取到okHttpCall對(duì)象。
- 最后,再把okHttpCall進(jìn)一步封裝并返回Call對(duì)象。 首先,創(chuàng)建retrofit對(duì)象的方法如下:
- Retrofit retrofit = new Retrofit.Builder()
- .baseUrl("https://api.github.com/")
- .build();
在創(chuàng)建retrofit對(duì)象的時(shí)候用到了build()方法,該方法的實(shí)現(xiàn)如下:
- public Retrofit build() {
- if (baseUrl == null) {
- throw new IllegalStateException("Base URL required.");
- }
- okhttp3.Call.Factory callFactory = this.callFactory;
- if (callFactory == null) {
- callFactory = new OkHttpClient(); //設(shè)置kHttpClient
- }
- Executor callbackExecutor = this.callbackExecutor;
- if (callbackExecutor == null) {
- callbackExecutor = platform.defaultCallbackExecutor(); //設(shè)置默認(rèn)回調(diào)執(zhí)行器
- }
- // Make a defensive copy of the adapters and add the default Call adapter.
- List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
- adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
- // Make a defensive copy of the converters.
- List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);
- return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
- callbackExecutor, validateEagerly); //返回新建的Retrofit對(duì)象
- }
該方法返回了一個(gè)Retrofit對(duì)象,通過retrofit對(duì)象創(chuàng)建網(wǎng)絡(luò)請(qǐng)求的接口的方式如下:
- NetApi repo = retrofit.create(NetApi.class);
retrofit對(duì)象的create()方法的實(shí)現(xiàn)如下:
- public <T> T create(final Class<T> service) {
- Utils.validateServiceInterface(service);
- if (validateEagerly) {
- eagerlyValidateMethods(service);
- }
- return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
- new InvocationHandler() {
- private final Platform platform = Platform.get();
- @Override public Object invoke(Object proxy, Method method, Object... args)
- throws Throwable {
- // If the method is a method from Object then defer to normal invocation.
- if (method.getDeclaringClass() == Object.class) {
- return method.invoke(this, args); //直接調(diào)用該方法
- }
- if (platform.isDefaultMethod(method)) {
- return platform.invokeDefaultMethod(method, service, proxy, args); //通過平臺(tái)對(duì)象調(diào)用該方法
- }
- ServiceMethod serviceMethod = loadServiceMethod(method); //獲取ServiceMethod對(duì)象
- OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args); //傳入?yún)?shù)生成okHttpCall對(duì)象
- return serviceMethod.callAdapter.adapt(okHttpCall); //執(zhí)行okHttpCall
- }
- });
- }
2.圖片加載庫(kù)對(duì)比
- Picasso:120K
- Glide:475K
- Fresco:3.4M
Android-Universal-Image-Loader:162K
圖片函數(shù)庫(kù)的選擇需要根據(jù)APP的具體情況而定,對(duì)于嚴(yán)重依賴圖片緩存的APP,例如壁紙類,圖片社交類APP來說,可以選擇最專業(yè)的Fresco。對(duì)于一般的APP,選擇Fresco會(huì)顯得比較重,畢竟Fresco3.4M的體量擺在這。根據(jù)APP對(duì)圖片的顯示和緩存的需求從低到高,我們可以對(duì)以上函數(shù)庫(kù)做一個(gè)排序。
Picasso < Android-Universal-Image-Loader < Glide < Fresco
介紹:
Picasso :和Square的網(wǎng)絡(luò)庫(kù)一起能發(fā)揮最大作用,因?yàn)镻icasso可以選擇將網(wǎng)絡(luò)請(qǐng)求的緩存部分交給了okhttp實(shí)現(xiàn)。
Glide:模仿了Picasso的API,而且在他的基礎(chǔ)上加了很多的擴(kuò)展(比如gif等支持),Glide默認(rèn)的Bitmap格式是RGB_565,比 Picasso默認(rèn)的ARGB_8888格式的內(nèi)存開銷要小一半;Picasso緩存的是全尺寸的(只緩存一種),而Glide緩存的是跟ImageView尺寸相同的(即5656和128128是兩個(gè)緩存) 。
FB的圖片加載框架Fresco:最大的優(yōu)勢(shì)在于5.0以下(最低2.3)的bitmap加載。在5.0以下系統(tǒng),F(xiàn)resco將圖片放到一個(gè)特別的內(nèi)存區(qū)域(Ashmem區(qū))。當(dāng)然,在圖片不顯示的時(shí)候,占用的內(nèi)存會(huì)自動(dòng)被釋放。這會(huì)使得APP更加流暢,減少因圖片內(nèi)存占用而引發(fā)的OOM。為什么說是5.0以下,因?yàn)樵?.0以后系統(tǒng)默認(rèn)就是存儲(chǔ)在Ashmem區(qū)了。
總結(jié):
Picasso所能實(shí)現(xiàn)的功能,Glide都能做,無非是所需的設(shè)置不同。但是Picasso體積比起Glide小太多如果項(xiàng)目中網(wǎng)絡(luò)請(qǐng)求本身用的就是okhttp或者retrofit(本質(zhì)還是okhttp),那么建議用Picasso,體積會(huì)小很多(Square全家桶的干活)。Glide的好處是大型的圖片流,比如gif、Video,如果你們是做美拍、愛拍這種視頻類應(yīng)用,建議使用。
Fresco在5.0以下的內(nèi)存優(yōu)化非常好,代價(jià)就是體積也非常的大,按體積算Fresco>Glide>Picasso
不過在使用起來也有些不便(小建議:他只能用內(nèi)置的一個(gè)ImageView來實(shí)現(xiàn)這些功能,用起來比較麻煩,我們通常是根據(jù)Fresco自己改改,直接使用他的Bitmap層)
3.各種json解析庫(kù)使用
(1)Google的Gson
Gson是目前功能最全的Json解析神器,Gson當(dāng)初是為因應(yīng)Google公司內(nèi)部需求而由Google自行研發(fā)而來,但自從在2008年五月公開發(fā)布第一版后已被許多公司或用戶應(yīng)用。Gson的應(yīng)用主要為toJson與fromJson兩個(gè)轉(zhuǎn)換函數(shù),無依賴,不需要例外額外的jar,能夠直接跑在JDK上。而在使用這種對(duì)象轉(zhuǎn)換之前需先創(chuàng)建好對(duì)象的類型以及其成員才能成功的將JSON字符串成功轉(zhuǎn)換成相對(duì)應(yīng)的對(duì)象。類里面只要有g(shù)et和set方法,Gson完全可以將復(fù)雜類型的json到bean或bean到j(luò)son的轉(zhuǎn)換,是JSON解析的神器。Gson在功能上面無可挑剔,但是性能上面比FastJson有所差距。
(2)阿里巴巴的FastJson
Fastjson是一個(gè)Java語言編寫的高性能的JSON處理器,由阿里巴巴公司開發(fā)。
無依賴,不需要例外額外的jar,能夠直接跑在JDK上。FastJson在復(fù)雜類型的Bean轉(zhuǎn)換Json上會(huì)出現(xiàn)一些問題,可能會(huì)出現(xiàn)引用的類型,導(dǎo)致Json轉(zhuǎn)換出錯(cuò),需要制定引用。FastJson采用獨(dú)創(chuàng)的算法,將parse的速度提升到極致,超過所有json庫(kù)。
綜上Json技術(shù)的比較,在項(xiàng)目選型的時(shí)候可以使用Google的Gson和阿里巴巴的FastJson兩種并行使用,如果只是功能要求,沒有性能要求,可以使用google的Gson,如果有性能上面的要求可以使用Gson將bean轉(zhuǎn)換json確保數(shù)據(jù)的正確,使用FastJson將Json轉(zhuǎn)換Bean






