RxJava 全解析:從原理到 Android 實戰

在 Android 開發中,異步任務處理是繞不開的核心場景 —— 網絡請求、數據庫操作、文件讀寫等都需要在后臺執行,而結果需回調到主線程更新 UI。傳統的 “Handler+Thread” 或 AsyncTask 不僅代碼冗余,還容易陷入 “回調地獄”(嵌套回調導致代碼可讀性差)。RxJava 作為一款基于響應式編程思想的異步框架,通過 “鏈式調用” 和 “操作符” 完美解決了這些問題,成為 Android 開發者的必備工具。本文將從 RxJava 的核心原理、核心組件到 Android 實戰,全面講解 RxJava 的使用。

一、RxJava 核心概念:什么是響應式編程?

1.1 響應式編程與 RxJava

響應式編程(Reactive Programming)是一種 “以數據流和變化傳播為核心” 的編程范式。簡單來說,就是將所有操作抽象為 “數據流”,數據的產生、轉換、消費都通過數據流傳遞,當數據變化時,依賴該數據的操作會自動響應。

RxJava(Reactive Extensions for Java)是響應式編程在 Java 平臺的實現,其核心思想是:

  • 以觀察者模式為基礎:通過 “被觀察者(Observable)” 產生數據,“觀察者(Observer)” 消費數據;
  • 支持鏈式操作:數據從產生到消費的過程中,可通過 “操作符(Operator)” 進行轉換(如過濾、映射、線程切換);
  • 異步非阻塞:默認在指定線程執行任務,避免阻塞主線程。

形象比喻:RxJava 就像 “水管系統”—— 被觀察者是 “水源”,操作符是 “水管中的過濾器 / 轉換器”,觀察者是 “水龍頭”。水流(數據)從水源出發,經過過濾、轉換后,最終從水龍頭流出被使用。

1.2 RxJava 解決的核心問題

對比傳統異步方式,RxJava 的優勢體現在三個方面:

1.消除回調地獄

傳統嵌套回調(如 “網絡請求 1→網絡請求 2→更新 UI”)的代碼如下:

// 傳統回調嵌套(回調地獄)
api.requestData1(new Callback() {@Overridepublic void onSuccess(Data1 data1) {api.requestData2(data1.getId(), new Callback() {@Overridepublic void onSuccess(Data2 data2) {runOnUiThread(() -> updateUI(data2));}@Overridepublic void onFailure(Throwable e) { ... }});}@Overridepublic void onFailure(Throwable e) { ... }
});

用 RxJava 實現的鏈式調用:

// RxJava鏈式調用(無嵌套)
api.rxRequestData1() // 第一步:請求數據1.flatMap(data1 -> api.rxRequestData2(data1.getId())) // 第二步:用數據1請求數據2.observeOn(AndroidSchedulers.mainThread()) // 切換到主線程.subscribe(data2 -> updateUI(data2), // 成功回調e -> handleError(e) // 錯誤回調);

2.線程切換簡化

傳統方式需通過 Handler 手動切換線程,RxJava 通過subscribeOn和observeOn兩個操作符即可指定 “任務執行線程” 和 “回調線程”,無需手動處理線程切換。

3.數據處理標準化

無論是網絡請求、數據庫查詢還是事件監聽,都可抽象為 Observable,通過統一的操作符進行處理(如過濾空數據、轉換數據格式),降低代碼耦合。

二、RxJava 核心組件:Observable 與 Observer

RxJava 的核心組件包括 “被觀察者(Observable)”“觀察者(Observer)”“訂閱(Subscribe)”“操作符(Operator)”,這四個組件構成了 RxJava 的基本骨架。

2.1 被觀察者(Observable):數據的產生者

Observable 是數據的 “源頭”,負責產生數據(可以是單個數據、多個數據或一個錯誤)。其生命周期包含三個關鍵事件:

  • onNext(T t):發送一條數據(可多次調用);
  • onError(Throwable e):發送一個錯誤(僅一次,發送后終止);
  • onComplete():表示數據發送完成(僅一次,發送后終止)。

簡單示例:創建一個發送 3 個整數的 Observable

// 創建被觀察者:發送1、2、3三個數據,然后完成
Observable<Integer> observable = Observable.create(emitter -> {emitter.onNext(1);emitter.onNext(2);emitter.onNext(3);emitter.onComplete(); // 數據發送完成
});

除了create,RxJava 還提供了便捷的創建方法:

  • Observable.just(t1, t2, ...):發送指定的單個 / 多個數據;
  • Observable.fromIterable(iterable):發送集合中的數據;
  • Observable.timer(delay, unit):延遲指定時間后發送一個 0L;
  • Observable.interval(period, unit):每隔指定時間發送一個遞增的 Long 值(如定時任務)。

示例:用just創建 Observable

Observable<String> observable = Observable.just("A", "B", "C"); // 發送A、B、C

2.2 觀察者(Observer):數據的消費者

Observer 是數據的 “消費者”,負責接收 Observable 發送的事件(onNext/onError/onComplete)并處理。RxJava 中有兩種常用的觀察者接口:

  1. Observer:完整的觀察者接口,需實現三個方法:
    Observer<String> observer = new Observer<String>() {@Overridepublic void onSubscribe(Disposable d) {// 訂閱時調用(可保存Disposable用于取消訂閱)mDisposable = d;}@Overridepublic void onNext(String s) {// 接收數據(對應Observable的onNext)Log.d("RxJava", "收到數據:" + s);}@Overridepublic void onError(Throwable e) {// 接收錯誤(對應Observable的onError)Log.e("RxJava", "發生錯誤:" + e.getMessage());}@Overridepublic void onComplete() {// 接收完成通知(對應Observable的onComplete)Log.d("RxJava", "數據接收完成");}
    };

  2. Consumer:簡化的觀察者(僅關注數據和錯誤),適合只需要處理 onNext 和 onError 的場景:
    // 只處理正常數據
    Consumer<String> onNext = s -> Log.d("RxJava", "收到數據:" + s);
    // 處理錯誤
    Consumer<Throwable> onError = e -> Log.e("RxJava", "錯誤:" + e.getMessage());

2.3 訂閱(Subscribe):連接 Observable 與 Observer

Observable 和 Observer 本身是獨立的,需通過 “訂閱(subscribe)” 建立關聯。調用observable.subscribe(observer)后,Observable 開始發送數據,Observer 開始接收數據。

訂閱示例

// Observable與Observer建立訂閱關系
Disposable disposable = observable.subscribe(s -> Log.d("RxJava", "收到:" + s), // onNexte -> Log.e("RxJava", "錯誤:" + e.getMessage()), // onError() -> Log.d("RxJava", "完成"), // onCompleted -> mDisposable = d // onSubscribe(可選)
);

關鍵對象:Disposable

subscribe方法返回的Disposable(可理解為 “開關”)用于取消訂閱:

  • disposable.dispose():切斷 Observable 與 Observer 的連接,Observer 不再接收數據;
  • disposable.isDisposed():判斷是否已取消訂閱。

為什么需要取消訂閱?

若頁面銷毀后,Observable 仍在發送數據并回調 UI,會導致內存泄漏(Observer 持有 Activity 引用)。需在onDestroy中調用dispose():

@Override
protected void onDestroy() {super.onDestroy();if (mDisposable != null && !mDisposable.isDisposed()) {mDisposable.dispose(); // 取消訂閱,避免內存泄漏}
}

2.4 操作符(Operator):數據的轉換器

操作符是 RxJava 的 “靈魂”,用于在數據從 Observable 到 Observer 的過程中進行轉換、過濾、組合等操作。RxJava 提供了上百種操作符,按功能可分為幾類核心操作符。

(1)轉換操作符:修改數據格式
  • map:將一種類型的數據轉換為另一種類型(一對一轉換)
    // 將Integer轉換為String(1→"Number:1")
    Observable.just(1, 2, 3).map(number -> "Number: " + number) // 轉換邏輯.subscribe(s -> Log.d("RxJava", s)); // 輸出:Number: 1、Number: 2、Number: 3

  • flatMap:將一個數據轉換為另一個 Observable(一對多轉換,用于嵌套請求)
    // 模擬:根據用戶ID獲取用戶信息,再根據用戶信息獲取訂單列表
    Observable.just(1001) // 用戶ID.flatMap(userId -> getUserInfo(userId)) // 轉換為“用戶信息Observable”.flatMap(userInfo -> getOrderList(userInfo.getUserId())) // 轉換為“訂單列表Observable”.subscribe(orders -> updateOrderUI(orders));

(2)過濾操作符:篩選數據
  • filter:按條件篩選數據(保留符合條件的數據)
    // 篩選偶數
    Observable.just(1, 2, 3, 4, 5).filter(number -> number % 2 == 0) // 條件:偶數.subscribe(number -> Log.d("RxJava", "偶數:" + number)); // 輸出:2、4

  • take:只取前 N 個數據
    // 只取前2個數據
    Observable.just("A", "B", "C", "D").take(2).subscribe(s -> Log.d("RxJava", s)); // 輸出:A、B

(3)線程切換操作符:指定執行線程

Android 開發中最常用的操作符,用于指定 “任務執行線程” 和 “回調線程”:

  • subscribeOn:指定 Observable 發送數據的線程(僅第一次調用有效);
  • observeOn:指定 Observer 接收數據的線程(可多次調用,每次調用切換后續線程)。

RxJava 通過Schedulers提供常用線程:

  • Schedulers.io():IO 密集型線程池(網絡請求、文件讀寫,線程數無上限);
  • Schedulers.computation():CPU 密集型線程池(數據計算,線程數 = CPU 核心數);
  • AndroidSchedulers.mainThread():Android 主線程(需引入 RxAndroid 庫)。

示例:網絡請求在 IO 線程執行,結果在主線程回調

// 需添加RxAndroid依賴(提供mainThread())
implementation 'io.reactivex.rxjava3:rxandroid:3.0.0'// 線程切換示例
Observable.fromCallable(() -> {// 耗時操作(在IO線程執行)return fetchDataFromNetwork(); // 網絡請求
})
.subscribeOn(Schedulers.io()) // 指定發送數據的線程(IO線程)
.observeOn(AndroidSchedulers.mainThread()) // 指定接收數據的線程(主線程)
.subscribe(data -> updateUI(data), // 在主線程更新UIe -> showError(e)
);
(4)組合操作符:合并多個 Observable
  • concat:按順序合并多個 Observable(前一個完成后再執行下一個)
    Observable<String> observable1 = Observable.just("A", "B");
    Observable<String> observable2 = Observable.just("C", "D");Observable.concat(observable1, observable2).subscribe(s -> Log.d("RxJava", s)); // 輸出:A、B、C、D

  • zip:將多個 Observable 的對應數據合并為一個新數據(如合并兩個網絡請求的結果)
    Observable<Integer> observable1 = Observable.just(1, 2);
    Observable<String> observable2 = Observable.just("A", "B");Observable.zip(observable1,observable2,(num, str) -> num + str // 合并邏輯:1+"A"→"1A",2+"B"→"2B"
    ).subscribe(s -> Log.d("RxJava", s)); // 輸出:1A、2B

三、RxJava 在 Android 中的典型應用場景

RxJava 在 Android 開發中的核心價值是 “簡化異步任務 + 線程切換”,以下是幾個高頻場景及實現。

3.1 網絡請求 + UI 更新

場景:調用接口獲取數據,在主線程更新 UI(避免手動線程切換)。

示例(結合 Retrofit,Retrofit 原生支持返回 Observable):

// 1. 定義Retrofit接口(返回Observable)
public interface ApiService {@GET("user/{id}")Observable<User> getUserInfo(@Path("id") String userId);
}// 2. 創建Retrofit實例
ApiService api = new Retrofit.Builder().baseUrl("https://api.example.com/").addConverterFactory(GsonConverterFactory.create()).addCallAdapterFactory(RxJava3CallAdapterFactory.create()) // 支持RxJava.build().create(ApiService.class);// 3. 發起請求并處理結果
Disposable disposable = api.getUserInfo("1001").subscribeOn(Schedulers.io()) // 網絡請求在IO線程.observeOn(AndroidSchedulers.mainThread()) // 回調在主線程.subscribe(user -> {// 更新UItvName.setText(user.getName());tvAge.setText(String.valueOf(user.getAge()));},e -> {// 處理錯誤(如網絡異常)Toast.makeText(this, "請求失敗", Toast.LENGTH_SHORT).show();});// 4. 頁面銷毀時取消訂閱
@Override
protected void onDestroy() {super.onDestroy();if (disposable != null && !disposable.isDisposed()) {disposable.dispose();}
}

3.2 數據庫操作 + 數據轉換

場景:從數據庫查詢數據,過濾無效數據后顯示(用操作符簡化數據處理)。

示例(結合 Room,Room 支持返回 Observable):

// 1. Room實體類
@Entity
public class User {@PrimaryKeypublic String id;public String name;public int age;
}// 2. Room DAO(返回Observable)
@Dao
public interface UserDao {@Query("SELECT * FROM user")Observable<List<User>> getAllUsers();
}// 3. 查詢并過濾數據(只顯示成年人)
Disposable disposable = userDao.getAllUsers().subscribeOn(Schedulers.io()) // 數據庫操作在IO線程.map(users -> {// 過濾年齡≥18的用戶(map轉換)List<User> adults = new ArrayList<>();for (User user : users) {if (user.age >= 18) {adults.add(user);}}return adults;}).observeOn(AndroidSchedulers.mainThread()) // 主線程更新列表.subscribe(adults -> userAdapter.setData(adults),e -> Log.e("DB", "查詢失敗:" + e.getMessage()));

3.3 定時任務 + 周期性操作

場景:實現倒計時(如驗證碼倒計時 60 秒)。

示例

// 倒計時60秒(從60到0)
Disposable disposable = Observable.interval(0, 1, TimeUnit.SECONDS) // 立即執行,每秒一次.take(61) // 只取61個數據(0-60).map(count -> 60 - count) // 轉換為倒計時(60,59,...,0).observeOn(AndroidSchedulers.mainThread()).subscribe(second -> {// 更新按鈕文字btnCode.setText(second + "秒后重新發送");btnCode.setEnabled(second == 0); // 倒計時結束后可點擊},e -> Log.e("Countdown", "錯誤:" + e.getMessage()));

3.4 合并多個請求結果

場景:需同時調用兩個接口,合并結果后顯示(如獲取用戶信息 + 用戶訂單)。

示例(用 zip 合并兩個請求):

// 1. 兩個接口請求
Observable<User> userObservable = api.getUserInfo("1001");
Observable<List<Order>> ordersObservable = api.getOrderList("1001");// 2. 合并結果
Disposable disposable = Observable.zip(userObservable,ordersObservable,(user, orders) -> new UserWithOrders(user, orders) // 合并為新對象
)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(userWithOrders -> {// 顯示用戶信息和訂單showUserInfo(userWithOrders.user);showOrders(userWithOrders.orders);},e -> Toast.makeText(this, "請求失敗", Toast.LENGTH_SHORT).show()
);

四、RxJava 高級技巧與注意事項

4.1 避免內存泄漏:規范管理 Disposable

內存泄漏是 RxJava 最常見的問題,根本原因是 “Observer 持有 Activity/Fragment 引用,且未取消訂閱”。解決方法:

  1. 使用 CompositeDisposable 管理多個 Disposable

當有多個訂閱時,用CompositeDisposable統一管理:

private CompositeDisposable mCompositeDisposable = new CompositeDisposable();// 添加訂閱
mCompositeDisposable.add(disposable1);
mCompositeDisposable.add(disposable2);// 取消所有訂閱(在onDestroy中)
@Override
protected void onDestroy() {super.onDestroy();mCompositeDisposable.dispose(); // 一次性取消所有訂閱
}
  1. 使用弱引用(WeakReference)

在 Observer 中若需引用 Activity,用弱引用避免強持有:

Observer<User> observer = new Observer<User>() {private WeakReference<MainActivity> activityRef;public Observer(MainActivity activity) {activityRef = new WeakReference<>(activity);}@Overridepublic void onNext(User user) {MainActivity activity = activityRef.get();if (activity != null && !activity.isFinishing()) {activity.updateUI(user); // 僅當Activity有效時更新}}// ...其他方法
};

4.2 錯誤處理:全局統一處理異常

RxJava 中若未處理onError,會導致程序崩潰。可通過onErrorResumeNext或全局異常處理器統一處理:

// 局部錯誤處理(返回默認數據)
Observable.just("1001").flatMap(id -> api.getUserInfo(id).onErrorResumeNext(throwable -> {// 發生錯誤時返回默認用戶return Observable.just(new User("默認用戶", 0));})).subscribe(...);// 全局錯誤處理(通過Transformer)
public <T> ObservableTransformer<T, T> handleError() {return upstream -> upstream.onErrorResumeNext(throwable -> {Log.e("GlobalError", "錯誤:" + throwable.getMessage());return Observable.empty(); // 發生錯誤時發送空數據});
}// 使用全局處理器
api.getUserInfo("1001").compose(handleError()) // 應用全局錯誤處理.subscribe(...);

4.3 操作符濫用:避免過度鏈式調用

雖然鏈式調用簡潔,但過度使用操作符會導致:

  • 性能損耗:每個操作符都會創建新的 Observable,增加內存開銷;
  • 可讀性下降:過長的鏈式調用(如 10 個以上操作符)難以調試。

建議

  • 合并重復操作(如多個 map 可合并為一個);
  • 復雜轉換邏輯提取為單獨方法;
  • 避免不必要的操作符(如無需轉換時不使用 map)。

4.4 RxJava3 的變化

目前 RxJava 已發展到 RxJava3,相比 RxJava2 的主要變化:

  • 移除Observable.OnSubscribe,改用ObservableSource;
  • 強化空安全(禁止發送 null 值,否則拋出異常);
  • 操作符命名更規范(如flatMapIterable替代flatMap的部分功能)。

建議直接使用 RxJava3,避免兼容舊版本問題。

五、RxJava 與其他框架的對比

框架

優勢

劣勢

適用場景

RxJava

操作符豐富,靈活度高,支持復雜數據處理

學習成本高,依賴較多

復雜異步場景(多請求合并、數據轉換)

Kotlin 協程

語言級支持,輕量級,無額外依賴

缺乏操作符,復雜轉換需手動實現

簡單異步任務,Kotlin 項目

LiveData

生命周期感知,自動取消訂閱

操作符少,不支持復雜轉換

數據與 UI 綁定(配合 ViewModel)

最佳實踐

  • 簡單場景(如單一網絡請求):Kotlin 協程更簡潔;
  • 復雜場景(多請求合并、數據過濾):RxJava 更高效;
  • UI 數據監聽:LiveData(或 RxJava+Lifecycle)。

六、總結

RxJava 的核心價值在于將異步任務 “數據流化”,通過觀察者模式和操作符簡化數據的產生、轉換、消費流程。其在 Android 開發中的核心應用是:

  • 替代 Handler/AsyncTask:用subscribeOn和observeOn簡化線程切換;
  • 消除回調地獄:通過 flatMap 等操作符將嵌套回調轉為鏈式調用;
  • 統一數據處理:用操作符實現數據過濾、轉換、合并,代碼更簡潔。

學習 RxJava 的關鍵是 “理解觀察者模式” 和 “掌握核心操作符”,而非死記硬背所有操作符。實際開發中,應根據場景選擇合適的操作符,避免過度設計。同時,務必注意 “取消訂閱” 以防止內存泄漏 —— 這是 RxJava 使用的第一準則。

掌握 RxJava 后,你會發現異步任務處理從 “繁瑣的回調嵌套” 變成 “流暢的鏈式調用”,代碼可讀性和可維護性將大幅提升。

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

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

相關文章

OpenCV 官翻7 - 對象檢測

文章目錄ArUco 標記檢測標記與字典標記物創建標記檢測姿態估計選擇字典預定義字典自動生成字典手動定義字典檢測器參數閾值處理adaptiveThreshConstant輪廓過濾minMarkerPerimeterRate 與 maxMarkerPerimeterRatepolygonalApproxAccuracyRateminCornerDistanceRateminMarkerDis…

【Oracle】ORACLE OMF說明

ORACLE OMF (Oracle Managed Files) 是 Oracle 數據庫提供的一項自動化文件管理功能。它的核心目的是簡化數據庫管理員&#xff08;DBA&#xff09;對數據庫底層操作系統文件的管理工作。 以下是 OMF 的關鍵要點&#xff1a; 核心功能&#xff1a;自動命名和定位文件 在創建數據…

408考研逐題詳解:2010年第35題——RIP協議

2010年第35題 某自治系統內采用 RIP 協議&#xff0c;若該自治系統內的路由器 R1 收到其鄰居路由器 R2 的距離矢量&#xff0c;距離矢量中包含信息 <net1, 16>&#xff0c;則能得出的結論是&#xff08; &#xff09; A. R2 可以經過 R1 到達 net1&#xff0c;跳數為17 …

http與https的主要區別是什么?

什么是HTTP&#xff1f; HTTP&#xff08;HyperText Transfer Protocol&#xff0c;超文本傳輸協議&#xff09;是互聯網上應用最為廣泛的一種網絡協議。它構成了Web數據通信的基礎&#xff0c;并定義了客戶端和服務器之間如何請求和傳遞網頁信息。當您在瀏覽器中輸入一個網址時…

STC89C52系列單片機簡介

STC89C52系列單片機是由中國宏晶科技&#xff08;STC&#xff09;推出的一款新一代增強型8051內核單片機。它不僅繼承了傳統8051指令系統的兼容性&#xff0c;還在性能、功耗、抗干擾能力以及性價比方面進行了全面提升&#xff0c;廣泛應用于各類嵌入式控制場景&#xff0c;如工…

基于 Docker 環境的 JupyterHub 詳細部署手冊

本文詳細介紹基于Docker Compose的單機版JupyterHub部署方案&#xff0c;通過容器化技術實現多用戶Notebook環境的快速搭建。方案采用官方JupyterHub鏡像&#xff0c;配置11個端口映射&#xff08;18000-18010&#xff09;支持用戶并發&#xff0c;通過數據卷掛載&#xff08;.…

常見的萬能密碼

目錄 1. 通用SQL注入 2. 登錄繞過 3. 密碼重置 1. 通用SQL注入 or 11-- " or 11-- or aa " or "a""a or 11# " or 11# or 11/* " or 11/* or 11 " or "1""1 2. 登錄繞過 admin-- admin or 11-- admin or aa …

04訓練windows電腦低算力顯卡如何部署pytorch實現GPU加速

大多數人用的電腦的顯卡配置可能沒有那么強,也就是說,我們很難享受到最新版本pytorch給我們帶來的模型訓練的速度和效率,為此,我們需要想辦法在現有顯卡情況下部署應用pytorch。 筆者有一臺電腦,顯卡算力很低,那么以該電腦為例,為大家介紹如何部署應用pytorch功能。 1…

PPT科研畫圖插件

PPT科研畫圖插件 iSlide- 讓PPT設計簡單起來 | PPT模板下載平臺iSlide - 簡單&#xff0c;好用的PPT插件&#xff01;擁有30萬 原創可商用PPT模板&#xff0c;PPT主題素材&#xff0c;PPT案例&#xff0c;PPT圖表&#xff0c;PPT圖示&#xff0c;PPT圖標&#xff0c;PPT插圖和8…

CSS實現背景圖片漸變透明

復合寫法background: linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, #FFF 82.5%),url(https://example.com/image.jpg) center / cover no-repeat;參數說明&#xff1a;linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, #FFF 82.5%)創建從下至上的垂直漸變&#xff…

基于pyside6的通用機器人遙控控制界面

1. 前言 這兩天需要幫一個朋友做一個簡單的遙控控制界面&#xff0c;用于控制一臺復合機器人(萬向輪底盤機械臂旋轉云臺)&#xff0c;在這里分享一下 2. 開發框架 由于朋友那邊的控制接口都是使用python來寫的&#xff0c;所以我這里也使用py來完成這個遙控界面的開發。但其…

【iOS】ZARA仿寫

【iOS】ZARA仿寫 文章目錄【iOS】ZARA仿寫前言首頁發現我的對姓名的更改總結前言 暑假第一個的任務仿寫ZARA 雖然不是特別難卻有很多小細節需要注意 首頁 點進程序出現的就是整個項目最主要的一個點&#xff0c;即首頁的無限輪播圖&#xff0c;不管是自動輪播還是手動滑動&a…

Kubernetes Pod 調度基礎

一、Replication Controller 和 ReplicaSet1、Replication ControllerReplication Controller&#xff08;復制控制器&#xff0c;RC&#xff09;RC 用來確保 Pod 副本數達到期望值&#xff0c;這樣可以確保一個或多個同類 Pod 總是可用的。如果存在的 Pod 數量大于設定的值&am…

菜鳥的C#學習(二)

文章目錄一、類的訪問1、普通類繼承抽象類2、普通類繼承抽象類&#xff0c;抽象類繼承接口&#xff0c;三者聯系二、類中方法的訪問2.1 抽象方法和虛方法2.2 虛方法和普通方法**1. 調用機制****2. 方法重寫****3. 設計意圖****4. 性能差異****5. 語法對比表****總結&#xff1a…

04 51單片機之數碼管顯示

文章目錄1、前言2、數碼管3、單個數碼管引腳定義3-1、單個共陰極3-2、單個共陽極3-3、單個數碼管引腳定義4、四位一體數碼管引腳定義4-1、四位一體共陰極數碼管4-2、四位一體共陽極數碼管4-3、四位一體數碼管引腳定義5、數碼管原理圖6、C51數組&#xff08;補充知識點&#xff…

【LLM】OpenRouter調用Anthropic Claude上下文緩存處理

背景 在使用OpenRouter調用Anthropic Claude大模型時&#xff0c;部分模型支持上下文緩存功能。當緩存命中時&#xff0c;調用成本會顯著降低。雖然像DeepSeek這類模型自帶上下文緩存機制&#xff0c;但本文主要針對構建Agent場景下&#xff0c;需要多次調用Anthropic Claude時…

【C++】第十七節—二叉搜索樹(概念+性能分析+增刪查+實現+使用場景)

好久不見&#xff0c;我是云邊有個稻草人 《C》本文所屬專欄—持續更新中—歡迎訂閱 目錄 一、二叉搜索樹的概念 二、二叉搜索樹的性能分析 三、二叉搜索樹的插入 SearchBinaryTree.h test.cpp 四、?叉搜索樹的查找 【只有一個3】 【有多個3】 五、?叉搜索樹的刪除…

Redis都有哪些數據結構,使用場景與原理解析

? String&#xff1a;字符串&#xff08;最常用、最簡單的類型&#xff09;&#x1f4cc; 應用場景&#xff1a;計數器&#xff08;如&#xff1a;頁面瀏覽量、點贊數、轉發數等&#xff09;緩存單個值&#xff08;如&#xff1a;token、驗證碼、用戶昵稱&#xff09;分布式鎖…

將EXCEL或者CSV轉換為鍵值對形式的Markdown文件

# 創建命令行參數解析器parser argparse.ArgumentParser(description將 CSV 或 Excel 文件轉換為帶標頭的 Markdown 格式)# 必需參數parser.add_argument(input_file, help輸入文件路徑 (CSV 或 Excel))parser.add_argument(output_file, help輸出 Markdown 文件路徑)# 可選參…

MySQL 配置性能優化實操指南:分版本5.7和8.0適配方案

在 MySQL 性能優化中&#xff0c;不同版本的特性差異會直接影響優化效果。本文基于 MySQL 5.7 和 8.0 兩個主流版本&#xff0c;通過版本適配的配置代碼、場景舉例和通俗解釋&#xff0c;讓優化方案更精準落地。一、硬件與系統配置優化&#xff08;基礎層優化&#xff09;1. 服…