Android Retrofit框架分析(三):自動切換回主線程;bulid的過程;create方法+ServiceMethod源碼了解

目錄

  1. Okhttp有什么不好?
  2. bulid的過程
  3. create方法+ServiceMethod
  4. call + enqueue的過程
  5. 為什么要學習源碼呢?

一、Okhttp有什么不好?

Okhttp本身來說,是一個挺好的網絡框架,但,對于開發者而言,使用起來,會過于繁瑣。下面我們看看一個代碼:

// 1?? 手動拼接URL和參數(容易出錯)
HttpUrl url = HttpUrl.parse("https://api.example.com/user").newBuilder().addQueryParameter("id", "123").build();// 2?? 創建請求對象
Request request = new Request.Builder().url(url).build();// 3?? 發起異步請求
OkHttpClient client = new OkHttpClient();
client.newCall(request).enqueue(new Callback() {@Overridepublic void onResponse(Call call, Response response) throws IOException {// 4?? 手動解析JSON(容易遺漏判空)String json = response.body().string();User user = new Gson().fromJson(json, User.class);// 5?? 手動切回主線程更新UI(忘記切換會崩潰)runOnUiThread(() -> {textView.setText(user.getName());});}@Overridepublic void onFailure(Call call, IOException e) {// 6?? 手動處理失敗邏輯(比如Toast錯誤)}
});

?問題總結??:

  • ??代碼臃腫??:每個請求都要寫重復代碼(拼參數、解析JSON、線程切換)。
  • ??維護困難??:如果接口路徑或參數變更,需要全局搜索修改。
  • ??容錯成本高??:手動處理空指針、JSON解析異常、線程安全問題。

下面我們看看Retrofit的代碼:

// 1?? 聲明接口(像寫文檔一樣直觀)
public interface ApiService {@GET("user")Call<User> getUser(@Query("id") String id); // 自動拼接參數
}// 2?? 發起請求(3行代碼搞定)
ApiService service = retrofit.create(ApiService.class);
service.getUser("123").enqueue(new Callback<User>() {@Overridepublic void onResponse(Call<User> call, Response<User> response) {// ? 自動解析JSON → User對象// ? 自動切回主線程textView.setText(response.body().getName());}
});

優化原理??:

  • ??聲明式API??:用注解代替手動拼參數(如@GET定義接口路徑,@Query自動拼接URL參數)。
  • ??自動解析??:通過GsonConverter直接將JSON轉成User對象。
  • ??線程安全??:回調時自動切換回主線程(背后是MainThreadExecutor)。

那么他是如何做到的呢?接下來,我們看看源碼。


二、bulid的過程

Retrofit retrofit = new Retrofit.Builder().baseUrl("https://api.example.com/")  // 必填:API根路徑.client(new OkHttpClient())          // 選填:自定義OkHttp(比如加日志攔截器).addConverterFactory(GsonConverterFactory.create()) // 選填:數據解析器.addCallAdapterFactory(RxJava2CallAdapterFactory.create()) // 選填:適配RxJava.build();

這個主要是做什么?可以理解為就是將所需的參數全部保存起來,方便后面使用,比如url,數據解析器等,都是為后面發起請求,和接收響應進行使用,使用bulid構建一個Retrofit,這就是bulid的作用。我們可以進入他的源碼看看:

比如addConverterFactory以及addCallAdapterFactory方法,都是使用List來保存起來,

在這里插入圖片描述

url也是

在這里插入圖片描述

然后使用bulid構建一個Retrofit。

在這里插入圖片描述

建造過程核心邏輯??:

  1. ??校驗必填參數??:比如baseUrl不能為空。
  2. ??設置默認組件??:如果沒配置CallAdapter,默認用ExecutorCallAdapterFactory(處理主線程回調)。
  3. ??組合所有配置??:將ConverterCallAdapter等組件打包到Retrofit對象中。

三、create方法+ServiceMethod

// 1?? 聲明接口(像寫文檔一樣直觀)
public interface ApiService {@GET("user")Call<User> getUser(@Query("id") String id); // 自動拼接參數
}// 2?? 發起請求(3行代碼搞定)
ApiService service = retrofit.create(ApiService.class);
service.getUser("123");

當我們調用retrofit.create方法的時候,我們看看內部做了什么。

在這里插入圖片描述

通過 Proxy.newProxyInstance 創建接口的代理對象,那么當我們調用service.getUser(“123”)的時候,代理對象的所有方法調用都會路由到 InvocationHandler.invoke()。讓所有的接口都走 invoke函數,這樣就可以攔截調用函數的執行,從而將網絡接口的參數配置歸一化。這個invoke方法,就是典型的AOP思想,在中間切開一個口。

invoke函數是如何完成網絡請求,從這個retrofit到okhttp呢?

接下來,我們看看loadServiceMethod方法

在這里插入圖片描述

這個方法返回了一個ServiceMethod,這里面主要做了什么?解析方法上的 @GET@POST 等注解,解析 @Query@Path@Body 等參數注解,解析結果會被緩存到 serviceMethodCache 避免重復解析。

每個接口方法(如 getUser())首次調用時都會生成專屬的 ServiceMethod,即使同一個接口中的不同方法(如 getUser()login()),也會生成不同的 ServiceMethod,然后通過 serviceMethodCache 的 ConcurrentHashMap 緩存起來,Key 為 Method 對象。


四、call + enqueue的過程

那么接口方法上的所有信息,參數都已經拿到了,也解析好了,接下來干嘛?我們繼續看回源碼這里,會調用invoke方法。

在這里插入圖片描述
在這里插入圖片描述

創建 OkHttpCall 對象,通過傳遞進來的參數,json解析成對應的bean,返回封裝了okhttp的call
在這里插入圖片描述

在這里插入圖片描述

call有了以后,接下來就是調用enqueue方法

在這里插入圖片描述

在得到response以后,要返回給主線程

在這里插入圖片描述

在這里插入圖片描述

在這里插入圖片描述

在這里插入圖片描述

底層還是handler。


五、為什么要學習源碼呢?

一開始的時候,在想,為什么要看源碼,看了源碼以后,你了解他的原理,你也可以運用他的技術,用到其他方面,比如注解的使用,動態代理的使用。

然后也能了解他的底層邏輯,后面我們寫retrofit代碼的時候,也會有一種恍然大悟的感覺,比如回調的這個地方,已經自動會切換到主線程。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/79973.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/79973.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/79973.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C++ STL 基礎與多線程安全性說明文檔

C STL 基礎與多線程安全性說明文檔 一、STL 簡介 STL&#xff08;Standard Template Library&#xff0c;標準模板庫&#xff09;是 C 標準庫的重要組成部分&#xff0c;提供了常用的數據結構和算法的泛型實現&#xff0c;極大地提高了代碼的復用性和開發效率。 STL 的六大組…

數據結構之圖的分類和存儲

圖 圖(Graph)G由兩個集合V和E組成&#xff0c;記為&#xff1a;G(V,E)&#xff0c;其中V是頂點的有窮非空集合(其實就是頂點)&#xff0c;E是V 中頂點偶對的有窮集合(就是邊)。V(G)和E(G)通常分別表示圖G的頂點集合以及邊集合&#xff0c;E(G)可以為空集合&#xff0c;但是此時…

擴增子分析|微生物生態網絡穩定性評估之魯棒性(Robustness)和易損性(Vulnerability)在R中實現

一、引言 周集中老師團隊于2021年在Nature climate change發表的文章&#xff0c;闡述了網絡穩定性評估的原理算法&#xff0c;并提供了完整的代碼。自此對微生物生態網絡的評估具有更全面的指標&#xff0c;自此網絡穩定性的評估廣受大家歡迎。本系列將介紹網絡穩定性之魯棒性…

setup 函數在 Vue 3 中的作用是什么?什么時候會執行

文章目錄 前言? 一、setup() 函數的作用是什么&#xff1f;? 二、setup() 什么時候執行&#xff1f;? 三、setup() 的參數? 四、setup() 中不能做什么&#xff1f;? 五、常見用法示例? 六、總結&#xff08;適合背誦或面試回答&#xff09; <script setup> 是 **Vu…

JDBC實現--保姆級教程~

本來以為寫過一個使用python與數據庫連接的文章&#xff0c;但是今天突然發現沒有&#xff0c;那就直接寫Java與數據庫連接的吧。當然如果大家有需要可以告訴我&#xff0c;有時間的話也可以寫一個的pymysql的使用的。 數據庫有很多種&#xff0c;接下來我就以MySQL為例來進行講…

Ubuntu18.04搭建samda服務器

一.什么是Samba服務器&#xff1f; Samba服務器是一種基于開源協議實現的網絡共享服務軟件&#xff0c;主要用于在不同操作系統&#xff08;如Windows、Linux、Unix&#xff09;之間實現文件和打印機共享功能。其核心目標是解決跨平臺資源共享的兼容性問題&#xff0c;尤其是在…

《分詞算法大揭秘:BPE、BBPE、WordPiece、ULM常見方法介紹》

分詞算法是自然語言處理&#xff08;NLP&#xff09;中的一個重要預處理步驟&#xff0c;它將文本分割成更小的單元&#xff08;如單詞、子詞或字符&#xff09;。以下是幾種常見的分詞算法&#xff1a;Byte Pair Encoding (BPE)、Byte-level BPE (BBPE)、WordPiece 和 Unigram…

WordPress01 - 后臺常用功能

最近些日子研究Wordpress&#xff0c;做些簡單的筆記。 怎么安裝Wordpress&#xff0c;怎么進的后臺&#xff0c;這些咱就不嘮了哈&#xff0c;網上到處是教程。 目錄 1&#xff0c;Wordpress的后臺 1-1&#xff0c; Posts(投稿) 1-2&#xff0c;Media(媒體) 1-3&#xf…

R8周:RNN實現阿爾茨海默病診斷

&#x1f368; 本文為&#x1f517;365天深度學習訓練營中的學習記錄博客 &#x1f356; 原作者&#xff1a;K同學啊 一、前期準備 1.設置GPU import numpy as np import pandas as pd import torch from torch import nn import torch.nn as nn import torch.nn.functi…

今天python練習題

目錄 一、每日一言 二、練習題 三、效果展示 四、下次題目 五、總結 一、每日一言 不要害怕失敗&#xff0c;失敗可能成為我們前進的動力&#xff01; 二、練習題 有列表lst [[1,2,3],[4,5,6],[7,8,9]],取出其中的元素1/5/9組成新的列表 # 有列表lst [[1,2,3],[4,5,6],[…

機器人強化學習入門學習筆記(二)

基于上一篇的《機器人強化學習入門學習筆記》,在基于 MuJoCo 的仿真強化學習訓練中,除了 PPO(Proximal Policy Optimization)之外,還有多個主流強化學習算法可用于訓練機器人直行或其他復雜動作。 ?? 一、常見強化學習算法對比(可用于 MuJoCo) 算法類型特點適合場景PP…

用 DuckDB 高效分析 JSON 數據:從入門到實戰

解析 JSON 文件進行分析常常充滿挑戰。無論你是在處理 API 響應、日志文件&#xff0c;還是應用數據&#xff0c;如果沒有合適的工具&#xff0c;分析 JSON 都會非常耗時。 借助 DuckDB&#xff0c;你可以直接用 SQL 查詢復雜的 JSON 文件&#xff0c;無需編寫復雜的解析代碼或…

從貼牌到品牌:出海官網如何讓中國制造“貴”起來?

在全球經濟一體化的當下&#xff0c;中美關稅戰如同一記重錘&#xff0c;給國際貿易格局帶來了巨大震蕩。自貿易摩擦爆發以來&#xff0c;雙方多次調整關稅政策&#xff0c;涉及的商品種類不斷增多&#xff0c;稅率持續攀升&#xff0c;眾多中國企業的出口業務遭受重創&#xf…

react-13react中外部css引入以及style內聯樣式(動態className與動態style)

1. 外部css文件 - 普通引入 1.1 創建一個 CSS 文件&#xff0c;MyComponent.css。 /* MyComponent.css */ .my-class {color: red;font-size: 20px; } 1.2 組件中import引入 import React from react; import ./MyComponent.css; // 引入 CSS 文件function MyComponent() {r…

n8n 與智能體構建:開發自動化 AI 作業的基礎平臺

n8n 是一款開源的自動化流程構建平臺&#xff0c;通過其模塊化節點系統&#xff0c;開發者可以快速實現跨平臺的任務編排、數據集成與智能交互。當 n8n 與大型語言模型&#xff08;LLM&#xff09;結合時&#xff0c;就能構建出具備感知、推理、執行能力的 AI 智能體&#xff0…

14.Spring Boot 3.1.5 集成 Spring Security 進行訪問控制

14.Spring Boot 3.1.5 集成 Spring Security 進行訪問控制 Spring Security 是一個強大且高度可定制的認證和訪問控制框架&#xff0c;專為基于 Spring 的應用程序設計。它為基于 Java EE 的企業應用程序提供了全面的安全解決方案&#xff0c;包括 Web 應用程序安全和方法級安…

Linux學習筆記(二):Linux權限管理

文章目錄 一、Linux下用戶的分類1. Linux下用戶分為兩類&#xff1a;2. 這兩類用戶如何進行切換呢&#xff1f;3. 短暫提權 二、何為權限1. 什么是權限2. Linux的文件后綴意義 三、修改權限1. 設置文件的訪問權限——chmod2. 修改文件擁有者——chown3. 修改文件所屬組——chgr…

學習alpha,第2個alpha

alphas (-1 * ts_corr(rank(ts_delta(log(volume), 2)), rank(((close - open) / open)), 6)) 先分析操作符從左到右 ts_corr: Pearson 相關度量兩個變量之間的線性關系。當變量呈正態分布且關系呈線性時&#xff0c;它最有效。 ts_corr(vwap, close, 20)是一個計算時間序列相…

Paddle Serving|部署一個自己的OCR識別服務器

前言 之前使用C部署了自己的OCR識別服務器&#xff0c;Socket網絡傳輸部分是自己寫的&#xff0c;回過頭來一看&#xff0c;自己犯傻了&#xff0c;PaddleOCR本來就有自己的OCR服務器項目&#xff0c;叫PaddleServing&#xff0c;這里記錄一下部署過程。 1 下載依賴環境 1.1 …

React Native【詳解】搭建開發環境,創建項目,啟動項目

下載安裝 node https://nodejs.cn/download/ 查看 npx 版本 npx -v若無 npx 則安裝 npm install -g npx創建項目 npx create-expo-applatestRN_demo 為自定義的項目名稱 下載安裝 Python 2.7 下載安裝 JAVA JDK https://www.oracle.com/java/technologies/downloads/#jdk24-…