- 移动开发
【免费下载链接】RxBinding
RxJava binding APIs for Android's UI widgets.
本篇文章以仓库根目录 CHANGELOG.md 为骨架,系统梳理 RxBinding 从 2015 年首个版本到 4.0.0 的完整演进脉络,包括 RxJava 1/2/3 三代适配、AndroidX 迁移、Kotlin-first 重构、Maven 坐标与包名变更、绑定 API 的增减与废弃清理,并结合仓库源码(如InitialValueObservable、各 Observable 实现与测试用例)逐一印证关键设计决策。读完本文,你将掌握 RxBinding 各版本的差异、绑定 API 的底层实现模式,以及从旧版本向com.jakewharton.rxbinding4迁移的完整清单。
一、CHANGELOG 纵览:一条主线与三次大版本跃迁
RxBinding 的变更日志记录了从0.1.0(2015-08-02)到4.0.0(2020-05-19)共 15 个正式版本的演进。纵观整份 CHANGELOG,演进主线非常清晰:
| 大版本 | 首个正式版本 | 对应的 RxJava 世代 | 坐标/包名前缀 | 关键主题 |
|---|---|---|---|---|
| 0.x | 0.1.0 (2015-08-02) | RxJava 1 | com.jakewharton.rxbinding | 模块版图成型、@CheckResult/@NonNull注解、Kotlin 模块起步 |
| 1.x | 1.0.0 (2016-12-01) | RxJava 1 | com.jakewharton.rxbinding | API 稳定,Toolbar/ViewPager/NestedScrollView 等大量新绑定 |
| 2.x | 2.0.0 (2017-03-06) | RxJava 2 | com.jakewharton.rxbinding2 | InitialValueObservable、事件类型重构、Void→Object |
| 3.x | 3.0.0 (2019-07-23) | RxJava 2 | com.jakewharton.rxbinding3 | AndroidX-only、Kotlin-first、事件类改为 Kotlindata class |
| 4.x | 4.0.0 (2020-05-19) | RxJava 3 | com.jakewharton.rxbinding4 | 仅升级 RxJava 3,无功能变化 |
三个关键版本节点分别是:2.0.0(全面转向 RxJava 2)、3.0.0(AndroidX 与 Kotlin-first 重构)、4.0.0(RxJava 3 支持)。仓库根目录 gradle.properties 显示当前开发版本为4.0.1-SNAPSHOT,GROUP为com.jakewharton.rxbinding4,与 4.0.0 的坐标体系一致。
二、4.0.0:全面切换 RxJava 3
Version 4.0.0 (2020-05-19):This version updates to support RxJava 3. No functional changes. The groupId and package name are now
com.jakewharton.rxbinding4.
4.0.0 是一次纯粹的平台升级:API 表面没有任何功能变化,只把底层从 RxJava 2 换成 RxJava 3,同时将 Maven groupId 与 Kotlin 包名统一为com.jakewharton.rxbinding4。这意味着 3.x 用户升级到 4.x 时,改动点集中在坐标与 import 语句。
当前仓库中的全部源码都已落在com.jakewharton.rxbinding4包下,例如 rxbinding/src/main/java/com/jakewharton/rxbinding4/InitialValueObservable.kt 顶部即为package com.jakewharton.rxbinding4,并直接 importio.reactivex.rxjava3.core.Observable与io.reactivex.rxjava3.core.Observer,这是 RxJava 3 的典型引用形态。
2.1 4.x 的模块划分与 Maven 坐标
根据 README.md 的 Download 章节,4.x 按平台/AndroidX/Material 三组提供依赖坐标:
Platform bindings:
implementation 'com.jakewharton.rxbinding4:rxbinding:4.0.0'AndroidX library bindings:
implementation 'com.jakewharton.rxbinding4:rxbinding-core:4.0.0' implementation 'com.jakewharton.rxbinding4:rxbinding-appcompat:4.0.0' implementation 'com.jakewharton.rxbinding4:rxbinding-drawerlayout:4.0.0' implementation 'com.jakewharton.rxbinding4:rxbinding-leanback:4.0.0' implementation 'com.jakewharton.rxbinding4:rxbinding-recyclerview:4.0.0' implementation 'com.jakewharton.rxbinding4:rxbinding-slidingpanelayout:4.0.0' implementation 'com.jakewharton.rxbinding4:rxbinding-swiperefreshlayout:4.0.0' implementation 'com.jakewharton.rxbinding4:rxbinding-viewpager:4.0.0' implementation 'com.jakewharton.rxbinding4:rxbinding-viewpager2:4.0.0'Google 'material' library bindings:
implementation 'com.jakewharton.rxbinding4:rxbinding-material:4.0.0'这些模块与 settings.gradle 中include的 11 个 Gradle 子项目一一对应:rxbinding、rxbinding-appcompat、rxbinding-core、rxbinding-drawerlayout、rxbinding-leanback、rxbinding-material、rxbinding-recyclerview、rxbinding-slidingpanelayout、rxbinding-swiperefreshlayout、rxbinding-viewpager、rxbinding-viewpager2(另有仅供测试使用的testing-utils模块)。
2.2 RxJava 3 在源码层的体现
以rxbinding-viewpager2模块为例,三处绑定实现均直接依赖 RxJava 3 类型:
- PageSelectedObservable.kt ——
ViewPager2.pageSelections()返回InitialValueObservable<Int>; - PageScrolledObservable.kt ——
ViewPager2.pageScrollEvents()返回Observable<PageScrollEvent>,其中PageScrollEvent是包含viewPager2、position、positionOffset、positionOffsetPixels的 Kotlindata class; - PageScrollStateChangedObservable.kt ——
ViewPager2.pageScrollStateChanges()返回Observable<Int>。
对应测试 RxViewPager2Test.kt 通过subscribeOn(AndroidSchedulers.mainThread())配合RecordingObserver验证了拖拽时按SCROLL_STATE_DRAGGING → SCROLL_STATE_SETTLING → SCROLL_STATE_IDLE的完整状态序列,以及dispose()之后不再产生任何事件的行为。
三、3.x:AndroidX 迁移与 Kotlin-first 重构
3.x 是 RxBinding 历史上变动最剧烈的一个大版本,CHANGELOG 在 3.0.0 与 3.0.0-alpha1 两条目中对核心变化做了完全一致的描述。
3.1 3.0.0(2019-07-23)的六项重大变更
- 新 Maven 坐标:
com.jakewharton.rxbinding3:rxbinding(etc.),包名改为com.jakewharton.rxbinding3.*。 - AndroidX-only:整个库只支持 AndroidX。需要继续使用旧 Support Library 的项目必须停留在2.2.0。
- Kotlin-first:
-kotlin后缀的独立 artifact 全部取消。Java 调用方拿到与之前相同的 API;Kotlin 调用方获得基于扩展函数的 API。事件类从 AutoValue 改为 Kotlindata class。 - 函数类型替换:RxJava 的
Predicate与 Java 的Callable不再使用,替换为 Kotlin 函数类型。Java 调用方仍可使用Function1,但官方鼓励直接使用 lambda。 Unit取代Object:不带任何信息的纯通知型 Observable 统一发射Unit(对 Kotlin 扩展用户而言这一点从早期就是如此)。- 清理:所有废弃方法被移除;一些琐碎的 consumer 工厂被移除,官方给出的替代方案是"直接向流订阅 lambda 来复刻其功能"。
此外,3.0.0 还修复了与 Material Design Componentsv1.1.0的二进制兼容性问题;3.0.0-alpha2 则修复了 AdapterView 回调中被点击 View 的可空性标注。
3.2 3.1.0(2019-11-22):新增rxbinding-viewpager2
3.1.0 唯一的新增是全新模块rxbinding-viewpager2,为ViewPager2提供三个绑定:
pageSelections—— 页面选中事件(发射页码索引);pageScrollEvents—— 页面滚动事件(含PageScrollEvent的偏移信息);pageScrollStateChanges—— 页面滚动状态变化(拖拽/稳定/归位)。
这些正是当前仓库rxbinding-viewpager2模块下三个源码文件所实现的能力,且pageSelections继承自InitialValueObservable,会在订阅时立刻发射viewPager2.currentItem作为初始值(见 PageSelectedObservable.kt 的initialValue实现与测试 RxViewPager2Test.kt 中assertEquals(0, recorder.takeNext())的断言)。
四、2.x:RxJava 2 时代的模块化与 API 收敛
4.1 2.0.0(2017-03-06):只支持 RxJava 2
2.0.0 宣布"only supports RxJava 2",并带来三项影响深远的 API 设计:
(1)InitialValueObservable<T>与skipInitialValue()
Bindings which emit an initial value now return an
InitialValueObservable<T>which offers a type-safe way to skip that value viaskipInitialValue().
源码实现位于 rxbinding/src/main/java/com/jakewharton/rxbinding4/InitialValueObservable.kt:它是一个继承自 RxJavaObservable<T>的抽象类,要求子类提供initialValue,在subscribeActual中先订阅监听器、再立刻发射初始值:
abstract class InitialValueObservable<T> : Observable<T>() { protected abstract val initialValue: T override fun subscribeActual(observer: Observer<in T>) { subscribeListener(observer) observer.onNext(initialValue) } protected abstract fun subscribeListener(observer: Observer<in T>) fun skipInitialValue(): Observable<T> = Skipped() private inner class Skipped : Observable<T>() { override fun subscribeActual(observer: Observer<in T>) { subscribeListener(observer) } } }从源码结构可以清晰地看出skipInitialValue()的实现机制:它返回一个"只订阅监听器、不发射初始值"的Skipped内部类,因此语义上等价于"过滤掉首个值",但比在流上加skip(1)更类型安全、意图更明确。这一设计在后续 3.x、4.x 中被完整保留。
(2)事件类型从枚举改为抽象类 + 子类
Event objects which previously contained an enum now use an abstract event type and subclasses for easier filtering using the
ofType(Class)operator.
在此之前,事件对象内部用一个 enum 区分事件种类;2.0.0 改为"抽象事件基类 + 具体子类",从而可以直接用 RxJava 的ofType(Class)操作符做类型过滤,例如只关心onPageSelected而不关心其他回调。
(3)Void改为Object
Bindings which previously emitted null using the
Voidtype now useObjectand omit an opaque item instance for which no guarantees are provided.
此前用Void类型、实际发射null的绑定,现在统一发射一个不透明的Object实例。CHANGELOG 明确警告:不要依赖这个实例是否相同、相等或不同——它只是一个通知信号。结合当前源码可见,纯通知型绑定(如 ViewClickObservable.kt 的View.clicks())在 Kotlin-first 的 3.x/4.x 中进一步演化为发射Unit。
4.2 2.1.x:细节修复与 consumer 废弃
- 2.1.0(2018-01-30):新增
rxbinding-design的FloatingActionButton.visibility(显示/隐藏 FAB);Snackbar dismisses 改用 add/remove 回调方式;开始废弃"直接委托给某个方法"的简单 consumer,官方示例是RxView.enabled(view)应改为方法引用view::setEnabled;同时把@RequiresApi注解传播到 Kotlin 扩展上。 - 2.1.1(2018-02-12):为 consumer 补充 ProGuard 规则以避免 AutoValue 注解告警;移除无用的
BuildConfig类;移除 Kotlin 扩展中的 Java 互操作检查(这些检查本就存在于其委托的 Java 代码中)。
4.3 2.2.0(2018-09-25):Java 8 字节码与两个新绑定
- 新增
rxbinding-support-v4的ViewPager.pageScrollEvents; - 新增
rxbinding-recyclerview-v7的RecyclerView.flingEvents; - Target Java 8 bytecode:要求使用 AGP 3.2 或更高版本并开启 Java 8 source/target 兼容;
- 废弃
RxMenuItemCompat(不再需要,直接用RxMenuItem); - 继续废弃"简单 consumer",引导用户改用方法引用。
flingEvents在 4.x 仓库中的实现见 RecyclerViewFlingEventObservable.kt:它通过RecyclerView.OnFlingListener发射包含velocityX/velocityY的RecyclerViewFlingEvent(data class),并在onDispose()时将onFlingListener置空以解除引用。
五、1.0 时代:API 稳定与新绑定批量落地
5.1 1.0.0(2016-12-01)
1.0.0 是首个稳定版本,新增绑定覆盖平台、AppCompat、Design、Support v4 四组模块:
rxbinding:Toolbar的title/titleRes/subtitle/subtitleRes;View的keys(按键事件)。rxbinding-appcompat-v7:Toolbar的title/titleRes/subtitle/subtitleRes。rxbinding-design:BottomNavigationView.itemSelections(导航项选中)。rxbinding-support-v4:NestedScrollView.scrollChangeEvents;SlidingPaneLayout的open/panelOpens/panelSlides;ViewPager的pageScrollStateChanges/currentItem。
同时做了一项依赖瘦身:rxbinding-support-v4现在只依赖support-core-ui。此外还修复了若干 Kotlin/Java 互操作细节:KotlinAction的泛型在适用场景正确允许 null;修正TextViewAfterTextChangeEvent.editable与TextViewEditorActionEvent.keyEvent的可空性标注——这两处可空性设计在 4.x 源码中依然可见,例如 TextViewAfterTextChangeEventObservable.kt 中data class TextViewAfterTextChangeEvent(val view: TextView, val editable: Editable?)。
5.2 1.0.1(2017-02-28)
仅一个修复:降低 Kotlin 模块的方法数开销(Reduce method count cost for Kotlin modules)。
六、0.x:早期演进与模块版图成型
6.1 0.1.0(2015-08-02):Initial release
首个版本发布,确立了"为平台与 Support Library 的 UI 控件提供 RxJava 绑定 API"的项目定位。
6.2 0.2.0(2015-08-23):三大新模块与注解规范
- 新模块:
rxbinding-appcompat-v7(AppCompat)、rxbinding-design(Design Support Library)、rxbinding-recyclerview-v7(RecyclerView),均同时提供对应的-kotlin变体。 - 新绑定:
RxSearchView:queryTextChanges/queryTextChangeEvents/query;RxToolbar.itemClicks;RxNavigationView.itemSelections;RxSnackbar.dismisses;RxTabLayout:selections/selectionEvents/select;RxRecyclerView:scrollEvents/scrollStateChangeEvents;RxSwipeRefreshLayout:refreshes/refreshing;RxTextSwitcher:text/currentText;RxView:attaches/attachEvents/detaches。
- 注解规范:为会生成 lint 警告的方法添加
@CheckResult;为永不为 null 的方法/参数添加@NonNull,并移除显式 null 检查。 - 其他:Kotlin 模块更新到 v0.12.1230;Support Library 升到 v23.0.0;最低 SDK 版本提高到 14;修复 Kotlin 模块对 Java 模块的依赖关系。
6.3 0.3.0(2015-10-22):Leanback 模块与事件类型收敛
- 新模块:
rxbinding-leanback-v17(及-kotlin),面向 Leanback Support Library,提供RxSearchBar(searchQuery/searchQueryChanges/searchQueryChangeEvents)与RxSearchEditText.keyboardDismisses。 - 新绑定:覆盖
RxAutoCompleteTextView.itemClickEvents、RxCheckedTextView.checked、RxMenuItem全家族(actionViewEvents/checked/clicks/enabled/icon/iconRes/title/titleRes/visible)、RxSeekBar(userChanges/systemChanges)、RxTextView(afterTextChangeEvents/beforeTextChangeEvents/color/error/errorRes/hint/hintRes)、RxToolbar.navigationClicks、RxView(draws/globalLayouts/hovers/hoverEvents/layoutChanges/layoutChangeEvents/preDraws/scrollChangeEvents/systemUiVisibilityChanges)、RxViewGroup.changeEvents、Design 组的RxAppBarLayout.offsetChanges、RxSwipeDismissBehavior.dismisses、RxTextInputLayout系列、RecyclerView 组的RxRecyclerView.scrollStateChanges、RxRecyclerViewAdapter(childAttachStateChangeEvents/dataChanges)、Support v4 组的RxViewPager.pageSelections。 - 事件类型收敛:值无关紧要的绑定统一改为发射
Void(Kotlin 中为Unit);移除了一批"事件对象不携带任何额外信息(除源 View 外)"的重载,官方给出的迁移姿势是自行用map操作符合并,例如:
RxFoo.bar(sourceView).map(data -> new Pair<>(sourceView, data))被移除的重载包括RxCompoundButton.checkedChangeEvents、RxRadioGroup.checkedChangeEvents、RxRecyclerView.scrollStateChangeEvents、RxView.clickEvents/dragEvents/focusChangeEvents/hoverEvents/longClickEvents/touchEvents。这一决策与 4.x 源码中"事件对象只保留必要信息"的设计一脉相承。
6.4 0.4.0(2016-02-18):Kotlin 1.0 与更多平台绑定
- 新增
RxAbsListView.scrollEvents、RxAutoCompleteTextView(completionHint/threshold)、RxPopupMenu(itemClicks/dismisses,platform 与 appcompat 两组)、RxActionMenuView.itemClicks、RxTextInputLayout(error/errorRes)、RxMenuItemCompat.actionViewEvents。 - Kotlin 模块依赖更新到v1.0.0(Kotlin 1.0 正式版)。
- 移除 76 个多余的 synthetic accessor 方法,进一步压缩方法数。
七、绑定 API 背后的统一实现模式(源码级)
CHANGELOG 描述的是"变",而要理解这些绑定为何稳定可用,还需要看"不变"的部分。从当前 4.x 仓库源码可以归纳出一套贯穿所有模块的统一实现模式:
7.1 主线程检查:checkMainThread
绝大多数绑定在订阅时调用 rxbinding/src/main/java/com/jakewharton/rxbinding4/internal/mainThread.kt 中的checkMainThread:若当前线程不是主线程(Looper.myLooper() != Looper.getMainLooper()),则立即通过onSubscribe(Disposable.empty())+onError(IllegalStateException(...))拒绝订阅,保证 Android UI 回调只在主线程被触碰。例如 ViewClickObservable.kt 与 RecyclerViewFlingEventObservable.kt 都以此为前置条件。
7.2 监听器生命周期:MainThreadDisposable+ 解绑
每个 Observable 内部都持有一个同时实现"平台监听器接口"与MainThreadDisposable的内部类Listener:
- 订阅时:
observer.onSubscribe(listener)把Disposable交给下游,然后注册监听器(如view.setOnClickListener(listener)); - 发射时:先判断
!isDisposed,再observer.onNext(...); - 取消时:在
onDispose()中反注册监听器(如view.setOnClickListener(null)/removeOnPageChangeListener(this))。
Kotlin 文档注释(KDoc)明确警告:Observable 会强引用View,必须退订以释放引用,否则可能造成内存泄漏。这与 CHANGELOG 中反复出现的"Unsubscribe to free this reference"是一致的。
7.3 初始值绑定与纯事件绑定的分界
- 需要初始值的绑定(如
queryTextChanges、pageSelections、afterTextChangeEvents)继承InitialValueObservable<T>,订阅即发射当前状态(view.query、view.currentItem、view.editableText),见 SearchViewQueryTextChangesObservable.kt; - 纯事件绑定(如
clicks、pageScrollStateChanges)继承普通Observable<T>,订阅时不发射任何值。测试 RxViewTest.java 中clicks()的o.assertNoMoreEvents(); // No initial value.正是对这一语义的验证。
7.4 事件类 = Kotlindata class
3.0.0 将事件类从 AutoValue 改为 Kotlindata class后,每个事件类型都自动获得equals/hashCode/toString与解构能力。仓库中TextViewAfterTextChangeEvent、RecyclerViewFlingEvent、PageScrollEvent、SearchViewQueryTextEvent等都是这一形态的典型代表(rxbinding/src/main/java/com/jakewharton/rxbinding4/widget/TextViewAfterTextChangeEventObservable.kt、rxbinding-recyclerview/src/main/java/com/jakewharton/rxbinding4/recyclerview/RecyclerViewFlingEventObservable.kt、rxbinding-viewpager2/src/main/java/com/jakewharton/rxbinding4/viewpager2/PageScrolledObservable.kt)。
7.5 "consumer 工厂"的消亡与替代
CHANGELOG 在 2.1.0/2.2.0 废弃、3.0.0 移除"直接委托给方法"的简单 consumer。以 ViewVisibilityConsumer.kt 为例,它本身是"把 Boolean 映射为View.VISIBLE/GONE"的消费者,其visibilityWhenFalse参数被严格限定为INVISIBLE或GONE(require校验,VISIBLE会被拒绝)。Material 模块中的 FloatingActionButtonVisibilityConsumer.kt 则是对show()/hide()的封装。对于这类能力,3.0.0 的建议是"直接向流订阅 lambda"(例如view::setEnabled式的方法引用)来替代工厂方法。
八、升级路线图:从旧版本迁移到 rxbinding4
综合 CHANGELOG,从任意旧版本升级到 4.x 需要依次跨越三条主线:
- RxJava 世代升级:1.x → 2.x 引入
InitialValueObservable、事件类型改抽象类+子类、Void→Object;3.x → 4.x 是纯 RxJava 3 切换,无功能变化。若项目仍停留在 RxJava 1,需先完成Observable语义差异(如背压、Single/Completable等)的适配。 - AndroidX 迁移:3.0.0 起库为 AndroidX-only;仍在使用旧 Support Library 的项目只能停留在2.2.0,或先完成自身 AndroidX 迁移再升级。
- Kotlin-first API 形态:3.0.0 起
-kotlinartifact 消失,事件类改为data class,Predicate/Callable改为 Kotlin 函数类型,Object通知改为Unit,废弃方法与琐碎 consumer 全部移除。Java 调用方继续使用Function1即可,推荐用 lambda。
升级时的坐标对照(group 前缀随版本变化):
| 版本世代 | groupId 示例 | 包名前缀 |
|---|---|---|
| 1.x | com.jakewharton.rxbinding:rxbinding:1.0.1 | com.jakewharton.rxbinding |
| 2.x | com.jakewharton.rxbinding2:rxbinding:2.2.0 | com.jakewharton.rxbinding2 |
| 3.x | com.jakewharton.rxbinding3:rxbinding:3.1.0 | com.jakewharton.rxbinding3 |
| 4.x | com.jakewharton.rxbinding4:rxbinding:4.0.0 | com.jakewharton.rxbinding4 |
注:2.x 时代的模块名带
-v7后缀(如rxbinding-appcompat-v7、rxbinding-recyclerview-v7),3.x/4.x 起已简化为无后缀形式(rxbinding-appcompat、rxbinding-recyclerview),4.x 还新增了rxbinding-core与rxbinding-viewpager2等模块。
九、总结
RxBinding 的 CHANGELOG 是理解其设计哲学的极佳入口:它始终围绕"为 Android UI 控件提供 RxJava 绑定"这一主题,历经三代 RxJava、一次 AndroidX 迁移、一次 Kotlin-first 重构,在持续扩充绑定覆盖面的同时,不断收敛事件类型、规范注解、清理废弃 API。当前仓库的 4.x 源码(11 个 Gradle 模块、统一的InitialValueObservable基类、checkMainThread主线程校验与MainThreadDisposable生命周期管理)正是这份演进史的最终落点——从 CHANGELOG.md 出发,对照 settings.gradle、README.md 与各模块源码,即可完整还原这一演进全貌,并据此制定切实可行的迁移方案。
- 移动开发
【免费下载链接】RxBinding
RxJava binding APIs for Android's UI widgets.
相关推荐
docker-mailserver 版本演进全解:从 v7 到 v16 的架构变迁与升级迁移指南
docker mailserver 版本演进全解:从 v7 到 v16 的架构变迁与升级迁移指南 本文以 CHANGELOG.md https://link.g
后端通信云原生NeMo Guardrails 版本演进全解析:从 0.1.0 到 0.24.1 的架构变迁、关键特性与升级指南
NeMo Guardrails 版本演进全解析:从 0.1.0 到 0.24.1 的架构变迁、关键特性与升级指南 NeMo Guardrails 是 NVIDI
人工智能大模型AI 安全治理模型安全内容安全提示词注入防护RAGODrive 固件演进全解析:从 0.1.0 到 0.5.6 的版本脉络、功能变迁与 API 迁移指南
ODrive 固件演进全解析:从 0.1.0 到 0.5.6 的版本脉络、功能变迁与 API 迁移指南 导读 本文以 ODrive 仓库根目录的 CHANGEL
嵌入式固件硬件开发智能硬件机器人
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考