Android開源庫——RxJava和RxAndroid

RxJava和RxAndroid是什么?

RxJava是基于JVM的響應式擴展,用于編寫異步代碼

RxAndroid是關于Android的RxJava綁定

RxJava和RxAndroid使用

依賴

implementation 'io.reactivex.rxjava3:rxjava:3.1.0'
implementation 'io.reactivex.rxjava3:rxandroid:3.0.2'

使用過程

如下模擬在子線程中進行耗時操作,并將結果返回到主線程中處理

  • Flowable:將要進行的操作
  • subscribeOn():操作要運行的線程
  • observeOn() :處理結果要運行的線程
  • subscribe():處理結果
public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Flowable.fromCallable(() -> {Thread.sleep(3000);return "Done";}).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(System.out::println, Throwable::printStackTrace);}
}

內存泄漏問題

若Activity退出后,線程仍未執行完,會導致內存泄漏,需要在onDestroy()將任務取消

public class MainActivity extends AppCompatActivity {CompositeDisposable mCompositeDisposable  = new CompositeDisposable();@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Disposable disposable = Flowable.fromCallable(() -> {Thread.sleep(3000);return "Done";}).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(System.out::println, Throwable::printStackTrace);mCompositeDisposable.add(disposable);}@Overrideprotected void onDestroy() {super.onDestroy();mCompositeDisposable.dispose();}
}

RxJava源碼解析

Publisher

Publisher用于發布數據,Subscriber通過subscribe()訂閱數據

public interface Publisher<T> {public void subscribe(Subscriber<? super T> s);
}

Subscriber

Subscriber接收Publisher發布的數據

  • onSubscribe():subscribe()回調函數,回調前會創建Subscription用于控制數據發布和停止
  • onNext():當Subscription調用request()時會調用onNext()發布數據
  • onError():處理接收到的錯誤
  • onComplete():處理完成的情況
public interface Subscriber<T> {public void onSubscribe(Subscription s);public void onNext(T t);public void onError(Throwable t);public void onComplete();
}

Subscription

Subscription表示Publisher和Subscriber的對應關系

  • request():向Publisher請求數據
  • cancel():讓Publisher停止發布數據
public interface Subscription {public void request(long n);public void cancel();
}

Scheduler

createWorker()用于創建Worker ,具體的調度工作由Worker的schedule()完成

public abstract class Scheduler {public abstract Worker createWorker();public abstract static class Worker implements Disposable {@NonNullpublic Disposable schedule(@NonNull Runnable run) {return schedule(run, 0L, TimeUnit.NANOSECONDS);}public abstract Disposable schedule(@NonNull Runnable run, long delay, @NonNull TimeUnit unit);}
}

source傳遞過程

fromCallable()創建FlowableFromCallable,傳遞callable

public abstract class Flowable<@NonNull T> implements Publisher<T> {public static <@NonNull T> Flowable<T> fromCallable(@NonNull Callable<? extends T> callable) {return RxJavaPlugins.onAssembly(new FlowableFromCallable<>(callable));}
}

subscribeOn()創建FlowableSubscribeOn,傳遞this(即FlowableFromCallable)作為source

public abstract class Flowable<@NonNull T> implements Publisher<T> {public final Flowable<T> subscribeOn(@NonNull Scheduler scheduler) {Objects.requireNonNull(scheduler, "scheduler is null");return subscribeOn(scheduler, !(this instanceof FlowableCreate));}public final Flowable<T> subscribeOn(@NonNull Scheduler scheduler, boolean requestOn) {Objects.requireNonNull(scheduler, "scheduler is null");return RxJavaPlugins.onAssembly(new FlowableSubscribeOn<>(this, scheduler, requestOn));}
}

observeOn()創建FlowableObserveOn,傳遞this(即FlowableSubscribeOn)作為source

public abstract class Flowable<@NonNull T> implements Publisher<T> {public final Flowable<T> observeOn(@NonNull Scheduler scheduler) {return observeOn(scheduler, false, bufferSize());}public final Flowable<T> observeOn(@NonNull Scheduler scheduler, boolean delayError, int bufferSize) {Objects.requireNonNull(scheduler, "scheduler is null");ObjectHelper.verifyPositive(bufferSize, "bufferSize");return RxJavaPlugins.onAssembly(new FlowableObserveOn<>(this, scheduler, delayError, bufferSize));}
}

即依次將自身當作Flowable,作為參數source傳遞給下一個Flowable

subscribe()流程

subscribe()最終調用具體Flowable的subscribeActual()

public abstract class Flowable<@NonNull T> implements Publisher<T> {......public final Disposable subscribe(@NonNull Consumer<? super T> onNext, @NonNull Consumer<? super Throwable> onError) {return subscribe(onNext, onError, Functions.EMPTY_ACTION);}public final Disposable subscribe(@NonNull Consumer<? super T> onNext, @NonNull Consumer<? super Throwable> onError,@NonNull Action onComplete) {.....LambdaSubscriber<T> ls = new LambdaSubscriber<>(onNext, onError, onComplete, FlowableInternalHelper.RequestMax.INSTANCE);subscribe(ls);return ls;}public final void subscribe(@NonNull FlowableSubscriber<? super T> subscriber) {try {Subscriber<? super T> flowableSubscriber = RxJavaPlugins.onSubscribe(this, subscriber);......subscribeActual(flowableSubscriber);}......}protected abstract void subscribeActual(@NonNull Subscriber<? super T> subscriber);
}

調用過程和傳遞過程是相反的,先調用FlowableObserveOn的subscribeActual()

public final class FlowableObserveOn<T> extends AbstractFlowableWithUpstream<T, T> {......@Overridepublic void subscribeActual(Subscriber<? super T> s) {Worker worker = scheduler.createWorker();if (s instanceof ConditionalSubscriber) {.....} else {source.subscribe(new ObserveOnSubscriber<>(s, worker, delayError, prefetch));}}}

上面的source就是上一層傳遞下來的FlowableSubscribeOn,即調用到FlowableSubscribeOn的subscribeActual()

public final class FlowableSubscribeOn<T> extends AbstractFlowableWithUpstream<T , T> {......@Overridepublic void subscribeActual(final Subscriber<? super T> s) {Scheduler.Worker w = scheduler.createWorker();final SubscribeOnSubscriber<T> sos = new SubscribeOnSubscriber<>(s, w, source, nonScheduledRequests);.....w.schedule(sos);}static final class SubscribeOnSubscriber<T> extends AtomicReference<Thread>implements FlowableSubscriber<T>, Subscription, Runnable {......@Overridepublic void run() {lazySet(Thread.currentThread());Publisher<T> src = source;source = null;src.subscribe(this);}

schedule()最終會調用run()方法,lazySet()切換線程,上面的source就是上一層傳遞下來的FlowableFromCallable,即將到FlowableFromCallable的subscribeActual()放到指定線程中運行

public final class FlowableFromCallable<T> extends Flowable<T> implements Supplier<T> {final Callable<? extends T> callable;......@Overridepublic void subscribeActual(Subscriber<? super T> s) {DeferredScalarSubscription<T> deferred = new DeferredScalarSubscription<>(s);s.onSubscribe(deferred);T t;try {t = Objects.requireNonNull(callable.call(), "The callable returned a null value");} catch (Throwable ex) {Exceptions.throwIfFatal(ex);if (deferred.isCancelled()) {RxJavaPlugins.onError(ex);} else {s.onError(ex);}return;}deferred.complete(t);}......
}

上面若出錯回調onError(),否則調用downstream的onNext()傳遞結果

public class DeferredScalarSubscription<@NonNull T> extends BasicIntQueueSubscription<T> {public final void complete(T v) {int state = get();for (;;) {......if (state == HAS_REQUEST_NO_VALUE) {lazySet(HAS_REQUEST_HAS_VALUE);Subscriber<? super T> a = downstream;a.onNext(v);if (get() != CANCELLED) {a.onComplete();}return;}value = v;......}}
}

onNext()過程

調用FlowableSubscribeOn.SubscribeOnSubscriber的onNext(),調用downstream的onNext()傳遞結果

public final class FlowableSubscribeOn<T> extends AbstractFlowableWithUpstream<T , T> {static final class SubscribeOnSubscriber<T> extends AtomicReference<Thread>implements FlowableSubscriber<T>, Subscription, Runnable {@Overridepublic void onNext(T t) {downstream.onNext(t);}}
}

調用FlowableObserveOn.BaseObserveOnSubscriber的onNext()、trySchedule(),schedule()最終會調用run()方法,根據sourceMode判斷是同步還是異步

  • FlowableObserveOn.ObserveOnSubscriber的runSync()和runAsync()都調用downstream的onNext()傳遞結果
public final class FlowableObserveOn<T> extends AbstractFlowableWithUpstream<T, T> {.....abstract static class BaseObserveOnSubscriber<T>extends BasicIntQueueSubscription<T>implements FlowableSubscriber<T>, Runnable {@Overridepublic final void onNext(T t) {......trySchedule();}'final void trySchedule() {......worker.schedule(this);}@Overridepublic final void run() {if (outputFused) {runBackfused();} else if (sourceMode == SYNC) {runSync();} else {runAsync();}}}static final class ObserveOnSubscriber<T> extends BaseObserveOnSubscriber<T>implements FlowableSubscriber<T> {void runSync() {......final Subscriber<? super T> a = downstream;......for (;;) {......while (e != r) {......a.onNext(v);......}......}}.....@Overridevoid runAsync() {final Subscriber<? super T> a = downstream;for (;;) {......while (e != r) {.....a.onNext(v);.....}.....}}}
}

調用LambdaSubscriber的onNext(),通過傳入的Consumer消費掉最終的結果,即通過System.out::println打印出來

public final class LambdaSubscriber<T> extends AtomicReference<Subscription>implements FlowableSubscriber<T>, Subscription, Disposable, LambdaConsumerIntrospection {.....@Overridepublic void onNext(T t) {if (!isDisposed()) {try {onNext.accept(t);} catch (Throwable e) {Exceptions.throwIfFatal(e);get().cancel();onError(e);}}}
}

onSubscribe()和request()流程

FlowableFromCallable回調下一層的onSubscribe(),其將Subscription存到upstream

public final class FlowableFromCallable<T> extends Flowable<T> implements Supplier<T> {final Callable<? extends T> callable;@Overridepublic void subscribeActual(Subscriber<? super T> s) {DeferredScalarSubscription<T> deferred = new DeferredScalarSubscription<>(s);s.onSubscribe(deferred);......}
}public final class FlowableSubscribeOn<T> extends AbstractFlowableWithUpstream<T , T> {static final class SubscribeOnSubscriber<T> extends AtomicReference<Thread>implements FlowableSubscriber<T>, Subscription, Runnable {@Overridepublic void onSubscribe(Subscription s) {if (SubscriptionHelper.setOnce(this.upstream, s)) {......}}}
}

FlowableSubscribeOn回調下一層的onSubscribe(),其回調下一層的onSubscribe()和上一層的request()請求數據

public final class FlowableSubscribeOn<T> extends AbstractFlowableWithUpstream<T , T> {......@Overridepublic void subscribeActual(final Subscriber<? super T> s) {Scheduler.Worker w = scheduler.createWorker();final SubscribeOnSubscriber<T> sos = new SubscribeOnSubscriber<>(s, w, source, nonScheduledRequests);s.onSubscribe(sos);}   
}public final class FlowableObserveOn<T> extends AbstractFlowableWithUpstream<T, T> {static final class ObserveOnSubscriber<T> extends BaseObserveOnSubscriber<T>implements FlowableSubscriber<T> {......@Overridepublic void onSubscribe(Subscription s) {if (SubscriptionHelper.validate(this.upstream, s)) {this.upstream = s;......queue = new SpscArrayQueue<>(prefetch);downstream.onSubscribe(this);s.request(prefetch);}}}
}

LambdaSubscriber利用FlowableInternalHelper.RequestMax的accept()調用上一層的request(),從schedule()獲取數據

public final class LambdaSubscriber<T> extends AtomicReference<Subscription>implements FlowableSubscriber<T>, Subscription, Disposable, LambdaConsumerIntrospection {@Overridepublic void onSubscribe(Subscription s) {if (SubscriptionHelper.setOnce(this, s)) {try {onSubscribe.accept(this);} catch (Throwable ex) {......}}}}public final class FlowableInternalHelper {public enum RequestMax implements Consumer<Subscription> {INSTANCE;@Overridepublic void accept(Subscription t) {t.request(Long.MAX_VALUE);}}
}public final class FlowableObserveOn<T> extends AbstractFlowableWithUpstream<T, T> {abstract static class BaseObserveOnSubscriber<T>extends BasicIntQueueSubscription<T>implements FlowableSubscriber<T>, Runnable {@Overridepublic final void request(long n) {if (SubscriptionHelper.validate(n)) {BackpressureHelper.add(requested, n);trySchedule();}}final void trySchedule() {......worker.schedule(this);}}
}

FlowableSubscribeOn.SubscribeOnSubscriber的request()、requestUpstream()判斷當前線程,若未切換線程調用schedule()切換線程調用上一層的request()

public final class FlowableSubscribeOn<T> extends AbstractFlowableWithUpstream<T , T> {static final class SubscribeOnSubscriber<T> extends AtomicReference<Thread>implements FlowableSubscriber<T>, Subscription, Runnable {@Overridepublic void request(final long n) {if (SubscriptionHelper.validate(n)) {Subscription s = this.upstream.get();if (s != null) {requestUpstream(n, s);} else {......}}}}void requestUpstream(final long n, final Subscription s) {if (nonScheduledRequests || Thread.currentThread() == get()) {s.request(n);} else {worker.schedule(new Request(s, n));}}static final class Request implements Runnable {......@Overridepublic void run() {upstream.request(n);}}}
}

DeferredScalarSubscription接收到請求后,將值傳給downstream的onNext()

public class DeferredScalarSubscription<@NonNull T> extends BasicIntQueueSubscription<T> {@Overridepublic final void request(long n) {if (SubscriptionHelper.validate(n)) {for (;;) {int state = get();......if (state == NO_REQUEST_HAS_VALUE) {if (compareAndSet(NO_REQUEST_HAS_VALUE, HAS_REQUEST_HAS_VALUE)) {T v = value;if (v != null) {value = null;Subscriber<? super T> a = downstream;a.onNext(v);if (get() != CANCELLED) {a.onComplete();}}}return;}......}}}
}

Schedulers.io()調度過程

Schedulers.io() = Schedulers.IO = IOTask() = IoHolder.DEFAULT = IoScheduler()

public final class Schedulers {static final Scheduler IO;static final class IoHolder {static final Scheduler DEFAULT = new IoScheduler();}static {IO = RxJavaPlugins.initIoScheduler(new IOTask());}public static Scheduler io() {return RxJavaPlugins.onIoScheduler(IO);}static final class IOTask implements Supplier<Scheduler> {@Overridepublic Scheduler get() {return IoHolder.DEFAULT;}}
}

FlowableSubscribeOn的subscribeActual()通過IoScheduler創建Worker并調用schedule()

public final class FlowableSubscribeOn<T> extends AbstractFlowableWithUpstream<T , T> {......@Overridepublic void subscribeActual(final Subscriber<? super T> s) {Scheduler.Worker w = scheduler.createWorker();final SubscribeOnSubscriber<T> sos = new SubscribeOnSubscriber<>(s, w, source, nonScheduledRequests);.....w.schedule(sos);}
}

調用IoScheduler的createWorker()會返回EventLoopWorker

public final class IoScheduler extends Scheduler {@NonNull@Overridepublic Worker createWorker() {return new EventLoopWorker(pool.get());}
}

調用IoScheduler.EventLoopWorker的schedule()最終調用ThreadWorker的父類NewThreadWorker的scheduleActual()

public final class IoScheduler extends Scheduler {static final class EventLoopWorker extends Scheduler.Worker implements Runnable {@NonNull@Overridepublic Disposable schedule(@NonNull Runnable action, long delayTime, @NonNull TimeUnit unit) {......return threadWorker.scheduleActual(action, delayTime, unit, tasks);}}static final class ThreadWorker extends NewThreadWorker {......}
}

調用scheduleActual()將Runnable封裝成ScheduledRunnable,通過ScheduledThreadPoolExecutor的submit()或schedule()提交

public class NewThreadWorker extends Scheduler.Worker implements Disposable {private final ScheduledExecutorService executor;volatile boolean disposed;public NewThreadWorker(ThreadFactory threadFactory) {executor = SchedulerPoolFactory.create(threadFactory);}@NonNullpublic ScheduledRunnable scheduleActual(final Runnable run, long delayTime, @NonNull TimeUnit unit, @Nullable DisposableContainer parent) {Runnable decoratedRun = RxJavaPlugins.onSchedule(run);ScheduledRunnable sr = new ScheduledRunnable(decoratedRun, parent);......Future<?> f;try {if (delayTime <= 0) {f = executor.submit((Callable<Object>)sr);} else {f = executor.schedule((Callable<Object>)sr, delayTime, unit);}sr.setFuture(f);} catch (RejectedExecutionException ex) {......}return sr;}
}public final class SchedulerPoolFactory {public static ScheduledExecutorService create(ThreadFactory factory) {final ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(1, factory);exec.setRemoveOnCancelPolicy(PURGE_ENABLED);return exec;}
}

線程池會調用FlowableSubscribeOn.SubscribeOnSubscriber的run()方法,SubscribeOnSubscriber繼承了AtomicReference<Thread>,lazySet()切換線程調用上一層source的subscribe()

public final class FlowableSubscribeOn<T> extends AbstractFlowableWithUpstream<T , T> {static final class SubscribeOnSubscriber<T> extends AtomicReference<Thread>implements FlowableSubscriber<T>, Subscription, Runnable {@Overridepublic void run() {lazySet(Thread.currentThread());Publisher<T> src = source;source = null;src.subscribe(this);}}}

AndroidSchedulers.mainThread()調度過程

AndroidSchedulers.mainThread() = AndroidSchedulers.MAIN_THREAD = MainHolder.DEFAULT = HandlerScheduler(),通過主線程Looper創建handler

public final class AndroidSchedulers {private static final class MainHolder {static final Scheduler DEFAULT = internalFrom(Looper.getMainLooper(), true);}private static final Scheduler MAIN_THREAD =RxAndroidPlugins.initMainThreadScheduler(() -> MainHolder.DEFAULT);}public static Scheduler mainThread() {return RxAndroidPlugins.onMainThreadScheduler(MAIN_THREAD);}private static Scheduler internalFrom(Looper looper, boolean async) {......return new HandlerScheduler(new Handler(looper), async);}
}

FlowableObserveOn的subscribeActual()通過IoScheduler創建Worker,在onNext()的trySchedule()調用schedule()

public final class FlowableObserveOn<T> extends AbstractFlowableWithUpstream<T, T> {@Overridepublic void subscribeActual(Subscriber<? super T> s) {Worker worker = scheduler.createWorker();if (s instanceof ConditionalSubscriber) {......} else {source.subscribe(new ObserveOnSubscriber<>(s, worker, delayError, prefetch));}}abstract static class BaseObserveOnSubscriber<T>extends BasicIntQueueSubscription<T>implements FlowableSubscriber<T>, Runnable {@Overridepublic final void onNext(T t) {......trySchedule();}final void trySchedule() {......worker.schedule(this);}}
}

調用HandlerScheduler的createWorker()返回HandlerWorker()

final class HandlerScheduler extends Scheduler {@Overridepublic Worker createWorker() {return new HandlerWorker(handler, async);}
}

調用HandlerScheduler.HandlerWorker的schedule(),將Runnable封裝成ScheduledRunnable,調用主線程handler的sendMessageDelayed()

final class HandlerScheduler extends Scheduler {private static final class HandlerWorker extends Worker {@Overridepublic Disposable schedule(Runnable run, long delay, TimeUnit unit) {......run = RxJavaPlugins.onSchedule(run);ScheduledRunnable scheduled = new ScheduledRunnable(handler, run);Message message = Message.obtain(handler, scheduled);message.obj = this; if (async) {message.setAsynchronous(true);}handler.sendMessageDelayed(message, unit.toMillis(delay));......return scheduled;}}
}

最終主線程會調用FlowableObserveOn.BaseObserveOnSubscriber的run(),根據sourceMode判斷是同步還是異步

  • FlowableObserveOn.ObserveOnSubscriber的runSync()和runAsync()都調用downstream的onNext()傳遞結果
public final class FlowableObserveOn<T> extends AbstractFlowableWithUpstream<T, T> {.....abstract static class BaseObserveOnSubscriber<T>extends BasicIntQueueSubscription<T>implements FlowableSubscriber<T>, Runnable {......@Overridepublic final void run() {if (outputFused) {runBackfused();} else if (sourceMode == SYNC) {runSync();} else {runAsync();}}}static final class ObserveOnSubscriber<T> extends BaseObserveOnSubscriber<T>implements FlowableSubscriber<T> {void runSync() {......final Subscriber<? super T> a = downstream;......for (;;) {......while (e != r) {......a.onNext(v);......}......}}.....@Overridevoid runAsync() {final Subscriber<? super T> a = downstream;for (;;) {......while (e != r) {.....a.onNext(v);.....}.....}}}
}

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

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

相關文章

并發基礎—三大問題:可見性、原子性、有序性

文章目錄 可見性原子性有序性&#xff08;指令重排&#xff09;經典的指令重排案例&#xff1a;單例模式的雙重檢查鎖volatile和synchronize都可以保證有序性并發壓測工具Jcstress證明指令重排會在多線程下出現問題&#xff08;了解&#xff09;CPU緩存分為三個級別&#xff1a…

PyTorch 入門學習

目錄 PyTorch 定義 核心作用 應用場景 Pytorch 基本語法 1. 張量的創建 2. 張量的類型轉換 3. 張量數值計算 4. 張量運算函數 5. 張量索引操作 6. 張量形狀操作 7. 張量拼接操作 8. 自動微分模塊 9. 案例-線性回歸案例 PyTorch 定義 PyTorch 是一個基于 Python 深…

Hive SQL 精進系列:REGEXP_REPLACE 函數的用法

目錄 一、引言二、REGEXP_REPLACE 函數基礎2.1 基本語法參數詳解2.2 簡單示例 三、REGEXP_REPLACE 函數的應用場景3.1 去除特殊字符3.2 統一字符串格式 四、REGEXP_REPLACE 與 REPLACE 函數的對比4.1 功能差異4.2 適用場景 五、REGEXP_REPLACE 與 REGEXP 函數的對比5.1 功能差異…

從0開始搭建微服務架構特別篇SpringCloud網關聚合knife4j

前言&#xff1a;總所周知項目開發接口測試需要knife4j&#xff0c;但是&#xff0c;微服務架構中微服務很多&#xff0c;模塊地址很多&#xff0c;需要統一管理api測試&#xff0c;就需要聚合在網關統一調用&#xff0c;本章&#xff0c;就說明如何通過網關聚合使用knife4j。 …

Spring Cloud 中的服務注冊與發現: Eureka詳解

1. 背景 1.1 問題描述 我們如果通過 RestTamplate 進行遠程調用時&#xff0c;URL 是寫死的&#xff0c;例如&#xff1a; String url "http://127.0.0.1:9090/product/" orderInfo.getProductId(); 當機器更換或者新增機器時&#xff0c;這個 URL 就需要相應地變…

網頁制作15-Javascipt時間特效の記錄網頁停留時間

01效果圖&#xff1a; 02運用&#xff1a; window.setTimeout&#xff08;&#xff09;刷新function&#xff08;&#xff09;函數document.forms&#xff08;&#xff09;&#xff1a;表單if條件語句window.alert&#xff08;&#xff09;窗口警示 03、操作代碼&#xff1a;…

【Rust基礎】排序和分組

排序 簡單排序 整數排序 #[test] fn test_sort(){let mut list vec![1, 5, 3, 2, 4];list.sort(); //?assert_eq!(list, vec![1, 2, 3, 4, 5]); }小數排序 #[test] fn test_sort(){let mut list vec![1, 5, 3, 2, 4];//? 不能直接使用sort&#xff0c;因為f32和f64未實現O…

C++ std::list超詳細指南:基礎實踐(手搓list)

目錄 一.核心特性 1.雙向循環鏈表結構 2.頭文件&#xff1a;#include 3.時間復雜度 4.內存特性 二.構造函數 三.list iterator的使用 1.學習list iterator之前我們要知道iterator的區分 ?編輯 2.begin()end() 3.rbegin()rend() 四.list關鍵接口 1.empty() 2. size…

996引擎 - 紅點系統

996引擎 - 紅點系統 總結NPC 紅點(TXT紅點)Lua 紅點1. Red_Point.lua2. UI_Ex.lua參考資料以下內容是在三端 lua 環境下測試的 總結 紅點系統分幾個部分組成。 M2中設置變量推送。 配置紅點表。 Envir\Data\cfg_redpoint.xls 2.1. UI元素中找到ID填寫 ids 列。 主界面掛載…

C語言——變量與常量

C語言中的變量與常量&#xff1a;簡潔易懂的指南 在C語言編程中&#xff0c;變量和常量是最基本的概念之一。理解它們的區別和使用方法對于編寫高效、可維護的代碼至關重要。本文將詳細介紹C語言中的變量和常量&#xff0c;并通過圖表和代碼示例幫助你更好地理解。 目錄 什么…

PySide(PyQt),使用types.MethodType動態定義事件

以PySide(PyQt)的圖片項為例&#xff0c;比如一個視窗的場景底圖是一個QGraphicsPixmapItem&#xff0c;需要修改它的鼠標滾輪事件&#xff0c;以實現鼠標滾輪縮放顯示的功能。為了達到這個目的&#xff0c;可以重新定義一個QGraphicsPixmapItem類&#xff0c;并重寫它的wheelE…

K8S學習之基礎三十一:k8s中RBAC 的核心概念

Kubernetes (k8s) 中的 RBAC&#xff08;Role-Based Access Control&#xff0c;基于角色的訪問控制&#xff09;是一種用于管理用戶和服務賬戶對集群資源訪問權限的機制。RBAC 允許管理員通過定義角色&#xff08;Role&#xff09;和角色綁定&#xff08;RoleBinding&#xff…

【eNSP實戰】三層交換機使用ACL實現網絡安全

拓圖 要求&#xff1a; vlan1可以訪問Internetvlan2和vlan3不能訪問Internet和vlan1vlan2和vlan3之間可以互相訪問PC配置如圖所示&#xff0c;這里不展示 LSW1接口vlan配置 vlan batch 10 20 30 # interface Vlanif1ip address 192.168.40.2 255.255.255.0 # interface Vla…

軟考系統架構師 — 1 考點分析

目錄 1 考點總結 1 考點總結 章節 內容 真題考察 緒論 1. 緒論 不考 計算機相關知識 2. 計算機系統基礎知識&#xff0c;新增計算機硬件、嵌入式、計算機語言、系統工程 對應計算機組成結構、操作系統、數據庫、計算機網絡、多媒體等知識點&#xff0c;整體分值在 10 …

在Eclipse 中使用 MyBatis 進行開發,通常需要以下步驟:

在Eclipse 中使用 MyBatis 進行開發&#xff0c;通常需要以下步驟&#xff1a; 1. 創建 Maven 項目 首先&#xff0c;在 Eclipse 中創建一個 Maven 項目。如果你還沒有安裝 Maven 插件&#xff0c;可以通過 Eclipse Marketplace 安裝 Maven 插件。 打開 Eclipse&#xff0c;選…

錯誤記錄: git 無法連接到github

錯誤記錄: git 無法連接到github 今天, 新建了一個github倉庫, 但從本地怎么都push不上去.并報錯 gitgithub.com: Permission denied (publickey). fatal: Could not read from remote repository.Please make sure you have the correct access rights and the repository e…

k8s 配置兩個deployment主機級別互斥部署

在 Kubernetes 中&#xff0c;要實現兩個 Deployment 的 Pod 在主機級別互斥部署&#xff0c;可以使用 podAntiAffinity 配置。通過設置 podAntiAffinity&#xff0c;可以確保兩個 Deployment 的 Pod 不會被調度到同一節點上。 實現步驟 定義 Deployment&#xff1a; 為每個…

Unity中WolrdSpace下的UI展示在上層

一、問題描述 Unity 中 Canvas使用World Space布局的UI&#xff0c;想讓它不被3d物體遮擋&#xff0c;始終顯示在上層。 二、解決方案 使用shader解決 在 UI 的材質中禁用深度測試&#xff08;ZTest&#xff09;&#xff0c;強制 UI 始終渲染在最上層。 Shader "Custo…

五子棋小游戲-簡單開發版

一、需求分析 開發一個基于 Pygame 庫的五子棋小游戲&#xff0c;允許兩名玩家在棋盤上輪流落子&#xff0c;當有一方達成五子連珠時游戲結束&#xff0c;顯示獲勝信息&#xff0c;并提供退出游戲和重新開始游戲的操作選項。 1.棋盤顯示 &#xff1a; 顯示一個 15x15 的五子棋…

基于C#的以太網通訊實現:TcpClient異步通訊詳解

基于C#的以太網通訊實現&#xff1a;TcpClient異步通訊詳解 在現代工業控制和物聯網應用中&#xff0c;以太網通訊是一種常見的數據傳輸方式。本文將介紹如何使用C#實現基于TCP協議的以太網通訊&#xff0c;并通過異步編程提高通訊效率。我們將使用TcpClient類來實現客戶端與服…