Android Retrofit 框架配置與構建模塊深入源碼分析(六)

一、引言

Retrofit 是一個在 Android 和 Java 開發中廣泛使用的類型安全的 HTTP 客戶端。它通過簡潔的 API 設計,使得網絡請求的處理變得高效且易于管理。配置與構建模塊作為 Retrofit 的基礎部分,承擔著初始化和定制 Retrofit 實例的重要任務。開發者可以通過該模塊對 Retrofit 進行多方面的配置,如設置基礎 URL、添加轉換器工廠、適配器工廠等,以滿足不同項目的需求。下面我們將深入到源碼級別,詳細剖析 Retrofit 配置與構建模塊的工作原理。

二、Retrofit 配置與構建的核心類:Retrofit.Builder

2.1 Retrofit.Builder 類概述

Retrofit.Builder 類是 Retrofit 配置與構建的核心類,它提供了一系列的方法用于設置 Retrofit 的各種參數,并最終構建出一個 Retrofit 實例。以下是 Retrofit.Builder 類的部分源碼:

java

public final class Retrofit {// 內部類,用于構建 Retrofit 實例public static final class Builder {// OkHttp 的 Call.Factory 實例,用于創建 HTTP 請求private okhttp3.Call.Factory callFactory;// 基礎 URLprivate HttpUrl baseUrl;// 轉換器工廠列表,用于處理請求和響應的數據轉換private final List<Converter.Factory> converterFactories = new ArrayList<>();// 適配器工廠列表,用于將 Call 對象轉換為其他類型private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>();// 回調執行器,用于處理回調操作private Executor callbackExecutor;// 是否提前驗證接口方法private boolean validateEagerly;// 構造函數,初始化默認的轉換器工廠和適配器工廠public Builder() {// 添加默認的轉換器工廠,用于處理基本數據類型的轉換converterFactories.add(new BuiltInConverters());}// 設置 Call.Factory 實例public Builder callFactory(okhttp3.Call.Factory factory) {this.callFactory = checkNotNull(factory, "factory == null");return this;}// 設置基礎 URLpublic Builder baseUrl(String baseUrl) {checkNotNull(baseUrl, "baseUrl == null");// 解析基礎 URL 為 HttpUrl 對象return baseUrl(HttpUrl.get(baseUrl));}// 設置基礎 URLpublic Builder baseUrl(HttpUrl baseUrl) {checkNotNull(baseUrl, "baseUrl == null");// 檢查基礎 URL 是否以 / 結尾List<String> pathSegments = baseUrl.pathSegments();if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);}this.baseUrl = baseUrl;return this;}// 添加轉換器工廠public Builder addConverterFactory(Converter.Factory factory) {converterFactories.add(checkNotNull(factory, "factory == null"));return this;}// 添加適配器工廠public Builder addCallAdapterFactory(CallAdapter.Factory factory) {callAdapterFactories.add(checkNotNull(factory, "factory == null"));return this;}// 設置回調執行器public Builder callbackExecutor(Executor executor) {this.callbackExecutor = checkNotNull(executor, "executor == null");return this;}// 設置是否提前驗證接口方法public Builder validateEagerly(boolean validateEagerly) {this.validateEagerly = validateEagerly;return this;}// 構建 Retrofit 實例public Retrofit build() {if (baseUrl == null) {throw new IllegalStateException("Base URL required.");}okhttp3.Call.Factory callFactory = this.callFactory;if (callFactory == null) {// 如果沒有設置 Call.Factory,默認使用 OkHttpClient 實例callFactory = new OkHttpClient();}Executor callbackExecutor = this.callbackExecutor;if (callbackExecutor == null) {// 如果沒有設置回調執行器,默認使用 Android 主線程執行器callbackExecutor = platform.defaultCallbackExecutor();}// 創建不可變的轉換器工廠列表List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);// 添加默認的轉換器工廠,用于處理字符串和字節數組的轉換converterFactories.add(new BuiltInConverters());// 創建不可變的適配器工廠列表List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);// 添加默認的適配器工廠,用于處理 Call 類型的返回值callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);}}
}

2.2 Retrofit.Builder 類的方法分析

2.2.1 構造函數

java

public Builder() {converterFactories.add(new BuiltInConverters());
}

在構造函數中,會添加一個 BuiltInConverters 實例到轉換器工廠列表中。BuiltInConverters 是一個內置的轉換器工廠,用于處理基本數據類型的轉換。

2.2.2 callFactory 方法

java

public Builder callFactory(okhttp3.Call.Factory factory) {this.callFactory = checkNotNull(factory, "factory == null");return this;
}

該方法用于設置 Call.Factory 實例,Call.Factory 是 OkHttp 中的一個接口,用于創建 Call 對象,Call 對象代表一個 HTTP 請求。這里會對傳入的 factory 進行非空檢查,確保其不為空。

2.2.3 baseUrl 方法

java

public Builder baseUrl(String baseUrl) {checkNotNull(baseUrl, "baseUrl == null");return baseUrl(HttpUrl.get(baseUrl));
}public Builder baseUrl(HttpUrl baseUrl) {checkNotNull(baseUrl, "baseUrl == null");List<String> pathSegments = baseUrl.pathSegments();if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);}this.baseUrl = baseUrl;return this;
}

這兩個重載的 baseUrl 方法用于設置基礎 URL。第一個方法接收一個字符串類型的 baseUrl,會將其解析為 HttpUrl 對象后調用第二個方法。第二個方法會對 baseUrl 進行檢查,確保其以 / 結尾,否則會拋出 IllegalArgumentException 異常。

2.2.4 addConverterFactory 方法

java

public Builder addConverterFactory(Converter.Factory factory) {converterFactories.add(checkNotNull(factory, "factory == null"));return this;
}

該方法用于添加轉換器工廠到轉換器工廠列表中。轉換器工廠用于創建轉換器,轉換器負責將請求參數序列化為 HTTP 請求體,以及將 HTTP 響應體反序列化為 Java 對象。這里會對傳入的 factory 進行非空檢查。

2.2.5 addCallAdapterFactory 方法

java

public Builder addCallAdapterFactory(CallAdapter.Factory factory) {callAdapterFactories.add(checkNotNull(factory, "factory == null"));return this;
}

該方法用于添加適配器工廠到適配器工廠列表中。適配器工廠用于創建適配器,適配器負責將 Call 對象轉換為其他類型,如 ObservableCompletable 等。這里會對傳入的 factory 進行非空檢查。

2.2.6 callbackExecutor 方法

java

public Builder callbackExecutor(Executor executor) {this.callbackExecutor = checkNotNull(executor, "executor == null");return this;
}

該方法用于設置回調執行器,回調執行器用于處理回調操作。這里會對傳入的 executor 進行非空檢查。

2.2.7 validateEagerly 方法

java

public Builder validateEagerly(boolean validateEagerly) {this.validateEagerly = validateEagerly;return this;
}

該方法用于設置是否提前驗證接口方法。如果設置為 true,Retrofit 會在創建服務接口實例時對接口方法進行驗證,而不是在調用方法時才驗證。

2.2.8 build 方法

java

public Retrofit build() {if (baseUrl == null) {throw new IllegalStateException("Base URL required.");}okhttp3.Call.Factory callFactory = this.callFactory;if (callFactory == null) {callFactory = new OkHttpClient();}Executor callbackExecutor = this.callbackExecutor;if (callbackExecutor == null) {callbackExecutor = platform.defaultCallbackExecutor();}List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);converterFactories.add(new BuiltInConverters());List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
}

build 方法用于構建 Retrofit 實例。在構建過程中,會進行一些必要的檢查和默認值的設置:

  • 檢查基礎 URL 是否為空,如果為空則拋出 IllegalStateException 異常。
  • 如果沒有設置 Call.Factory,則默認使用 OkHttpClient 實例。
  • 如果沒有設置回調執行器,則使用平臺默認的回調執行器。
  • 添加默認的轉換器工廠和適配器工廠到相應的列表中。
  • 最后使用這些配置創建一個 Retrofit 實例并返回。

三、配置與構建模塊的使用示例

3.1 基本配置

java

Retrofit retrofit = new Retrofit.Builder().baseUrl("https://api.example.com/").build();

在這個示例中,我們只設置了基礎 URL,其他配置使用默認值。build 方法會自動處理默認的 Call.Factory、回調執行器等配置。

3.2 自定義配置

java

OkHttpClient okHttpClient = new OkHttpClient.Builder().connectTimeout(10, TimeUnit.SECONDS).readTimeout(10, TimeUnit.SECONDS).writeTimeout(10, TimeUnit.SECONDS).build();Retrofit retrofit = new Retrofit.Builder().baseUrl("https://api.example.com/").callFactory(okHttpClient).addConverterFactory(GsonConverterFactory.create()).addCallAdapterFactory(RxJava2CallAdapterFactory.create()).callbackExecutor(Executors.newSingleThreadExecutor()).validateEagerly(true).build();

在這個示例中,我們進行了更詳細的配置:

  • 創建了一個自定義的 OkHttpClient 實例,并設置了連接超時、讀取超時和寫入超時時間。
  • 使用 callFactory 方法將自定義的 OkHttpClient 實例設置為 Call.Factory
  • 使用 addConverterFactory 方法添加了 GsonConverterFactory,用于處理 JSON 數據的轉換。
  • 使用 addCallAdapterFactory 方法添加了 RxJava2CallAdapterFactory,用于將 Call 對象轉換為 RxJava 的 Observable 等類型。
  • 使用 callbackExecutor 方法設置了一個單線程的執行器作為回調執行器。
  • 使用 validateEagerly 方法設置為提前驗證接口方法。

四、配置與構建模塊的高級用法

4.1 動態配置基礎 URL

在某些情況下,我們可能需要根據不同的環境動態配置基礎 URL。可以通過封裝 Retrofit.Builder 來實現這一點:

java

public class RetrofitClient {private static Retrofit retrofit;public static Retrofit getClient(String baseUrl) {if (retrofit == null) {retrofit = new Retrofit.Builder().baseUrl(baseUrl).addConverterFactory(GsonConverterFactory.create()).addCallAdapterFactory(RxJava2CallAdapterFactory.create()).build();}return retrofit;}
}

在使用時,可以根據不同的環境傳入不同的基礎 URL:

java

Retrofit retrofit = RetrofitClient.getClient("https://api.example.com/");

4.2 配置攔截器

可以通過自定義 OkHttpClient 并添加攔截器來實現對 HTTP 請求和響應的攔截和處理。以下是一個添加日志攔截器的示例:

java

import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;import java.io.IOException;public class RetrofitConfig {public static Retrofit getRetrofit() {// 創建日志攔截器HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);// 創建自定義的 OkHttpClient 并添加攔截器OkHttpClient okHttpClient = new OkHttpClient.Builder().addInterceptor(loggingInterceptor).addInterceptor(new Interceptor() {@Overridepublic Response intercept(Chain chain) throws IOException {Request originalRequest = chain.request();// 可以在這里對請求進行修改,如添加請求頭Request newRequest = originalRequest.newBuilder().header("Authorization", "Bearer your_token").build();return chain.proceed(newRequest);}}).build();return new Retrofit.Builder().baseUrl("https://api.example.com/").callFactory(okHttpClient).addConverterFactory(GsonConverterFactory.create()).build();}
}

在這個示例中,我們添加了一個日志攔截器用于打印請求和響應的詳細信息,還添加了一個自定義的攔截器用于在請求中添加請求頭。

五、配置與構建模塊的異常處理

5.1 基礎 URL 為空異常

build 方法中,如果基礎 URL 為空,會拋出 IllegalStateException 異常:

java

if (baseUrl == null) {throw new IllegalStateException("Base URL required.");
}

這是為了確保 Retrofit 實例在構建時必須有一個有效的基礎 URL。

5.2 其他異常

在配置過程中,如果傳入的參數為空,如 callFactoryconverterFactorycallAdapterFactorycallbackExecutor 等,會在相應的設置方法中拋出 NullPointerException 異常,因為這些方法都進行了非空檢查:

java

public Builder callFactory(okhttp3.Call.Factory factory) {this.callFactory = checkNotNull(factory, "factory == null");return this;
}

六、配置與構建模塊的性能優化

6.1 單例模式

為了避免重復創建 Retrofit 實例,可以使用單例模式。以下是一個簡單的單例實現:

java

public class RetrofitSingleton {private static Retrofit retrofit;private RetrofitSingleton() {}public static synchronized Retrofit getInstance() {if (retrofit == null) {retrofit = new Retrofit.Builder().baseUrl("https://api.example.com/").addConverterFactory(GsonConverterFactory.create()).addCallAdapterFactory(RxJava2CallAdapterFactory.create()).build();}return retrofit;}
}

使用單例模式可以減少內存開銷,提高性能。

6.2 合理配置 OkHttpClient

OkHttpClient 是 Retrofit 底層使用的 HTTP 客戶端,合理配置 OkHttpClient 可以提高性能。例如,可以設置連接池、緩存等:

java

OkHttpClient okHttpClient = new OkHttpClient.Builder().connectTimeout(10, TimeUnit.SECONDS).readTimeout(10, TimeUnit.SECONDS).writeTimeout(10, TimeUnit.SECONDS).connectionPool(new ConnectionPool(5, 5, TimeUnit.MINUTES)).cache(new Cache(cacheDirectory, cacheSize)).build();

在這個示例中,我們設置了連接超時、讀取超時和寫入超時時間,還設置了連接池和緩存。連接池可以復用已經建立的連接,減少連接建立的開銷;緩存可以避免重復的網絡請求,提高響應速度。

七、配置與構建模塊的未來發展趨勢

7.1 與更多的 HTTP 客戶端集成

目前 Retrofit 主要與 OkHttp 集成,未來可能會支持更多的 HTTP 客戶端,如 HttpURLConnection 等,以滿足不同開發者的需求。

7.2 更簡潔的配置方式

隨著 Android 開發的不斷發展,可能會出現更簡潔的配置方式,減少開發者的配置工作量。例如,通過注解或配置文件來進行配置。

7.3 更好的性能優化

未來的配置與構建模塊可能會進行更多的性能優化,如減少初始化時間、降低內存開銷等。可以通過優化內部的數據結構和算法來實現這些優化。

7.4 增強的錯誤處理和調試功能

配置與構建模塊可能會提供更詳細的錯誤信息和調試工具,幫助開發者更快地定位和解決問題。例如,在異常信息中提供更多的上下文信息,或者提供可視化的調試工具。

八、總結

Retrofit 的配置與構建模塊是整個框架的基礎,它提供了豐富的配置選項,使得開發者可以根據不同的需求對 Retrofit 進行定制。通過深入分析 Retrofit.Builder 類的源碼,我們了解了各個配置方法的作用和實現細節。在實際開發中,我們可以根據項目的需求進行合理的配置,如設置基礎 URL、添加轉換器工廠和適配器工廠、配置攔截器等。同時,我們還可以通過單例模式和合理配置 OkHttpClient 來提高性能。隨著 Android 開發的不斷發展,配置與構建模塊也可能會不斷改進和完善,為開發者提供更好的開發體驗。

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

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

相關文章

80.Dictionary 字典 C#例子

使用 C# 中的 Dictionary 數據結構 在 C# 中&#xff0c;Dictionary<TKey, TValue> 是一個非常強大的數據結構&#xff0c;用于存儲鍵值對。它提供了高效的查找、插入和刪除操作&#xff0c;適用于需要快速訪問數據的場景。本文將通過一個簡單的示例&#xff0c;介紹如何…

tomcat負載均衡配置

這里拿Nginx和之前做的Tomcat 多實例來實現tomcat負載均衡 1.準備多實例與nginx tomcat單機多實例部署-CSDN博客 2.配置nginx做負載均衡 upstream tomcat{ server 192.168.60.11:8081; server 192.168.60.11:8082; server 192.168.60.11:8083; } ser…

C語言中scanf(“%c“,s)會出現的問題

scanf("%c%c", &word[0], &word[1]);的行為與輸入緩沖區的內容密切相關。你提到輸入ab后&#xff0c;word[0]是\n&#xff0c;這通常是因為輸入緩沖區中殘留了換行符&#xff08;\n&#xff09;。 一、原因分析 換行符殘留 若在輸入ab之前有其他輸入操作&a…

SealOS部署k8s集群(單節點)

一、 先決條件 每個集群節點應該有不同的主機名。需要在 K8s 集群的第一個 master 節點上運行 sealos run 命令。建議使用干凈的操作系統來創建集群。不要自己裝 Docker&#xff01;支持大多數 Linux發行版&#xff0c;但內核版本建議5以上。例如&#xff1a;Ubuntu、CentOS、…

Linux 服務器安全配置:密碼復雜度與登錄超時設置

Linux服務器安全配置指南:密碼復雜度與登錄超時設置 一、密碼復雜度設置 通過PAM模塊pam_cracklib.so實現密碼強度策略,配置文件: system-auth該文件主要用于定義系統范圍內的認證策略,涵蓋了用戶登錄、su 命令切換用戶、sudo 權限提升等多種認證場景。當用戶嘗試進行系…

AI Agent開發框架分析:前端視角

1. Mastra (https://mastra.ai/docs) 優點&#xff1a; 提供直觀的界面構建器&#xff0c;適合無代碼/低代碼開發支持JavaScript/TypeScript&#xff0c;可直接集成到前端項目可視化工作流設計&#xff0c;降低入門門檻內置多種UI組件&#xff0c;加速前端開發 缺點&#xf…

linux上使用unsloth微調大模型的環境踩坑之路-4070ti、4090

我們實驗室有2套環境 一套&#xff1a;4070ti。安裝了cuda12.4 一套&#xff1a;3張4090.安裝了cuda12.4 現在開始給第一套裝能運行unsloth能運行的環境 第一步&#xff1a;開始創建虛擬環境 conda create -n test_env python3.11 第二步&#xff1a;進入虛擬環境 conda activa…

網絡安全演練有哪些形式

OPENVAS使用 1、確定指定IP是否能ping通 2、創建掃描目標 3、創建掃描任務&#xff08;scan management →newtask&#xff09; 4、開始任務start 5、查看掃描細節 6、查看掃描結果&#xff0c;包含漏洞詳細信息&#xff0c;亦可到處PDF文件 7、導出掃描結果報告 8、為…

ConcurrentModificationException:檢測到并發修改完美解決方法

&#x1f6a6; ConcurrentModificationException&#xff1a;檢測到并發修改完美解決方法 &#x1f4a1; 摘要 1. 什么是ConcurrentModificationException&#xff1f;&#x1f914; 2. ConcurrentModificationException的常見場景 &#x1f6a6; 2.1 使用for-each循環遍歷集合…

電路原理(電容 集成電路NE555)

電容 1.特性&#xff1a;充放電&#xff0c;隔直流&#xff0c;通交流 2.電容是通過聚集正負電荷來存儲電能的 3.電容充放電過程可等效為導通回路 4.多電容并聯可以把容量疊加&#xff0c;但是多電容串聯就不會&#xff0c;只會疊加電容的耐壓值。 6.電容充放電時相當于通路&a…

深入解析 React 最新特性:革新、應用與最佳實踐

深入解析 React 最新特性&#xff1a;革新、應用與最佳實踐 1. 引言 React 作為前端開發的核心技術之一&#xff0c;近年來不斷推出 新的 API 和優化機制&#xff0c;從 Concurrent Rendering&#xff08;并發模式&#xff09; 到 Server Components&#xff08;服務器組件&a…

【氮化鎵】高輸入功率應力誘導的GaN 在下的退化LNA退化

2019年,中國工程物理研究院電子工程研究所的Tong等人基于實驗與第一性原理計算方法,研究了Ka波段GaN低噪聲放大器(LNA)在高輸入功率應力下的退化機制。實驗結果表明,在27 GHz下施加1 W連續波(CW)輸入功率應力后,LNA的增益下降約1 dB,噪聲系數(NF)增加約0.7 dB。進一…

C#程序員接口調用工具與方法

作為專注于接口調用的C#軟件工程師&#xff0c;以下工具和方法能顯著提升開發效率與代碼質量&#xff1a; 一、接口開發與測試自動化工具 1. API測試與Mock工具 Postman Newman 支持RESTful/GraphQL接口調試與自動化測試&#xff0c;通過集合&#xff08;Collection&#xf…

Spring Boot項目中集成sa-token實現認證授權和OAuth 2.0第三方登錄

OAuth 2.0第三方登錄 OAuth 2.0 是一種授權協議&#xff0c;允許第三方應用在不暴露用戶密碼的情況下訪問用戶的資源。它通常用于第三方登錄場景&#xff0c;例如使用GitHub、Google等社交平臺進行登錄。 在sa-token框架中&#xff0c;OAuth 2.0第三方登錄可以通過集成sa-tok…

數字化新零售與 AI 大模型,如何重塑大健康賽道??

在數字化浪潮中&#xff0c;大健康賽道正經歷深刻變革。數字化新零售營銷模式的興起&#xff0c;與 AI 大模型的強大能力相結合&#xff0c;為大健康領域帶來了全新的發展機遇。 數字化新零售營銷模式融合線上線下&#xff0c;運用大數據、云計算分析消費者行為&#xff0c;實…

高速PCB設計(布線設計)

以下是針對高速PCB布線設計的綜合筆記&#xff0c;結合用戶提供的設計規范及行業通用原則整理而成&#xff1a; 一、關鍵信號布線原則 布線優先級 順序&#xff1a;射頻信號&#xff1e;中/低頻信號&#xff1e;時鐘信號&#xff1e;高速信號射頻信號需包地處理&#xff0c;線…

宇樹ROS1開源模型在ROS2中Gazebo中仿真

以GO1為例 1. CMakelists.txt更新語法 cmake_minimum_required(VERSION 3.8) project(go1_description) if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")add_compile_options(-Wall -Wextra -Wpedantic) endif() # find dependencies find…

嵌入式學習第二十四天--網絡 服務器

服務器模型 tcp服務器: socket bind listen accept recv/send close 1.支持多客戶端訪問 //單循環服務器 socket bind listen while(1) { accept while(1) { recv/send } } close 2.支持多客戶端同時訪問 (并發能力) 并發服務器 socket bind …

使用GPTQ量化Llama-3-8B大模型

使用GPTQ量化8B生成式語言模型 服務器配置&#xff1a;4*3090 描述&#xff1a;使用四張3090&#xff0c;分別進行單卡量化&#xff0c;多卡量化。并使用SGLang部署量化后的模型&#xff0c;使用GPTQ量化 原來的模型精度為FP16&#xff0c;量化為4bit 首先下載gptqmodel量化…

防汛應急包,快速響應,守護安全

根據中國水利部統計&#xff0c;自1949年以來&#xff0c;我國幾乎每年都面臨洪水威脅&#xff0c;其中20世紀90年代后洪澇災害頻率顯著增加&#xff0c;僅1990-2009年間就發生超4000起較大災害&#xff0c;直接經濟損失近3萬億元&#xff0c;受災人口達20億人次。在2020年長江…