0
# RxAndroid
1
2
RxAndroid provides Android-specific bindings for RxJava 2, offering schedulers for main thread execution and Looper-based scheduling. This minimal library adds essential Android integration to RxJava's reactive streams, making it easy to handle UI updates and background processing in Android applications.
3
4
## Package Information
5
6
- **Package Name**: io.reactivex.rxjava2:rxandroid
7
- **Package Type**: Maven (Android AAR)
8
- **Language**: Java
9
- **Version**: 2.1.1
10
- **Installation**: Add to your `build.gradle` dependencies: `implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'`
11
- **Minimum SDK**: Android API level 9
12
- **License**: Apache-2.0
13
14
## Core Imports
15
16
```java
17
import io.reactivex.android.schedulers.AndroidSchedulers;
18
import io.reactivex.android.MainThreadDisposable;
19
import io.reactivex.android.plugins.RxAndroidPlugins;
20
import io.reactivex.Scheduler;
21
import android.os.Looper;
22
```
23
24
## Basic Usage
25
26
```java
27
import io.reactivex.Observable;
28
import io.reactivex.android.schedulers.AndroidSchedulers;
29
import io.reactivex.schedulers.Schedulers;
30
31
// Schedule work on background thread and observe results on main thread
32
Observable.fromCallable(() -> {
33
// Background work (e.g., network call, database operation)
34
return processData();
35
})
36
.subscribeOn(Schedulers.io())
37
.observeOn(AndroidSchedulers.mainThread())
38
.subscribe(result -> {
39
// Update UI on main thread
40
updateUI(result);
41
});
42
43
// Custom Looper scheduling
44
HandlerThread handlerThread = new HandlerThread("Background");
45
handlerThread.start();
46
Scheduler customScheduler = AndroidSchedulers.from(handlerThread.getLooper());
47
48
Observable.just("data")
49
.observeOn(customScheduler)
50
.subscribe(data -> {
51
// Process on custom thread
52
});
53
```
54
55
## Capabilities
56
57
### Main Thread Scheduling
58
59
Android-specific scheduler that executes actions on the main UI thread.
60
61
```java { .api }
62
/**
63
* Returns a Scheduler which executes actions on the Android main thread.
64
* Thread-safe and can be called from any thread.
65
*/
66
public static Scheduler mainThread();
67
```
68
69
### Looper-Based Scheduling
70
71
Create schedulers that execute on specific Android Loopers.
72
73
```java { .api }
74
/**
75
* Returns a Scheduler which executes actions on the specified Looper.
76
* @param looper the Looper to schedule actions on
77
* @throws NullPointerException if looper is null
78
*/
79
public static Scheduler from(Looper looper);
80
81
/**
82
* Returns a Scheduler which executes actions on the specified Looper with async messaging option.
83
* @param looper the Looper to schedule actions on
84
* @param async if true, uses async messaging on API >= 16 to avoid VSYNC locking.
85
* Automatically set to false on API < 16. On API 16-21, validates that
86
* Message.setAsynchronous() is available before enabling async messaging.
87
* @throws NullPointerException if looper is null
88
*/
89
public static Scheduler from(Looper looper, boolean async);
90
```
91
92
**Usage Example:**
93
94
```java
95
// Create background thread with custom Looper
96
HandlerThread backgroundThread = new HandlerThread("MyBackground");
97
backgroundThread.start();
98
99
// Schedule work on custom Looper
100
Scheduler customScheduler = AndroidSchedulers.from(backgroundThread.getLooper());
101
Observable.just("work")
102
.observeOn(customScheduler)
103
.subscribe(item -> {
104
// Executes on custom background thread
105
});
106
107
// Using async messaging (API 16+)
108
Scheduler asyncScheduler = AndroidSchedulers.from(backgroundThread.getLooper(), true);
109
110
// Note: AndroidSchedulers uses HandlerScheduler internally for all Looper-based scheduling
111
```
112
113
### Main Thread Disposable
114
115
Abstract base class for creating disposables that ensure their disposal actions run on the main thread.
116
117
```java { .api }
118
/**
119
* Abstract class implementing Disposable with main thread disposal guarantee.
120
* Useful for UI-related subscriptions that need cleanup on the main thread.
121
*/
122
public abstract class MainThreadDisposable implements Disposable {
123
124
/**
125
* Verify that the calling thread is the Android main thread.
126
* Commonly used as precondition check in custom observables.
127
* @throws IllegalStateException when called from any thread other than main thread
128
*/
129
public static void verifyMainThread();
130
131
/**
132
* Returns whether this Disposable is disposed.
133
*/
134
public final boolean isDisposed();
135
136
/**
137
* Disposes this Disposable, ensuring onDispose() runs on main thread.
138
* Thread-safe - can be called from any thread.
139
*/
140
public final void dispose();
141
142
/**
143
* Called when disposal occurs, guaranteed to execute on main thread.
144
* Subclasses must implement this method to perform cleanup.
145
*/
146
protected abstract void onDispose();
147
}
148
```
149
150
**Usage Example:**
151
152
```java
153
public class CustomObservable extends Observable<String> {
154
@Override
155
protected void subscribeActual(Observer<? super String> observer) {
156
// Verify we're on main thread for UI access
157
MainThreadDisposable.verifyMainThread();
158
159
// Set up some UI listener or resource
160
setupUIListener();
161
162
observer.onSubscribe(new MainThreadDisposable() {
163
@Override
164
protected void onDispose() {
165
// Cleanup UI resources - guaranteed to run on main thread
166
cleanupUIListener();
167
}
168
});
169
170
observer.onNext("data");
171
observer.onComplete();
172
}
173
}
174
```
175
176
### Plugin System
177
178
Customization hooks for RxAndroid scheduler behavior, useful for testing and debugging.
179
180
```java { .api }
181
/**
182
* Sets a handler to customize main thread scheduler initialization.
183
* @param handler function to transform scheduler initialization
184
*/
185
public static void setInitMainThreadSchedulerHandler(Function<Callable<Scheduler>, Scheduler> handler);
186
187
/**
188
* Initializes main thread scheduler with optional handler transformation.
189
* @param scheduler callable that provides default scheduler
190
* @throws NullPointerException if scheduler is null
191
* @return transformed scheduler or default if no handler set
192
*/
193
public static Scheduler initMainThreadScheduler(Callable<Scheduler> scheduler);
194
195
/**
196
* Sets a handler to customize main thread scheduler instances.
197
* @param handler function to transform scheduler instances
198
*/
199
public static void setMainThreadSchedulerHandler(Function<Scheduler, Scheduler> handler);
200
201
/**
202
* Applies main thread scheduler handler if set.
203
* @param scheduler scheduler to potentially transform
204
* @throws NullPointerException if scheduler is null
205
* @return transformed scheduler or original if no handler set
206
*/
207
public static Scheduler onMainThreadScheduler(Scheduler scheduler);
208
209
/**
210
* Returns current init handler.
211
* @return handler function or null if not set
212
*/
213
public static Function<Callable<Scheduler>, Scheduler> getInitMainThreadSchedulerHandler();
214
215
/**
216
* Returns current main thread handler.
217
* @return handler function or null if not set
218
*/
219
public static Function<Scheduler, Scheduler> getOnMainThreadSchedulerHandler();
220
221
/**
222
* Removes all handlers and resets to default behavior.
223
*/
224
public static void reset();
225
```
226
227
**Usage Example:**
228
229
```java
230
// Replace main thread scheduler for testing
231
RxAndroidPlugins.setMainThreadSchedulerHandler(scheduler -> Schedulers.trampoline());
232
233
// Custom initialization
234
RxAndroidPlugins.setInitMainThreadSchedulerHandler(schedulerCallable -> {
235
return new CustomTestScheduler();
236
});
237
238
// Reset to defaults (typically in test teardown)
239
RxAndroidPlugins.reset();
240
```
241
242
## Types
243
244
```java { .api }
245
// From RxJava 2 - key types used by RxAndroid
246
interface Scheduler {
247
Disposable scheduleDirect(Runnable run);
248
Worker createWorker();
249
}
250
251
interface Disposable {
252
void dispose();
253
boolean isDisposed();
254
}
255
256
interface Function<T, R> {
257
R apply(T t) throws Exception;
258
}
259
260
// From Android SDK
261
class Looper {
262
static Looper getMainLooper();
263
static Looper myLooper();
264
}
265
```
266
267
## Error Handling
268
269
RxAndroid follows RxJava's error handling patterns:
270
271
- **NullPointerException**: Thrown when null parameters are passed to `AndroidSchedulers.from()` or `RxAndroidPlugins` methods
272
- **IllegalStateException**: Thrown by `MainThreadDisposable.verifyMainThread()` when called from non-main thread
273
- All exceptions propagate through RxJava's plugin system and can be handled using `RxJavaPlugins.setErrorHandler()`
274
275
## Thread Safety
276
277
- All public static methods in `AndroidSchedulers` and `RxAndroidPlugins` are thread-safe
278
- `MainThreadDisposable.dispose()` is thread-safe using atomic operations
279
- Plugin handlers are stored in volatile fields for safe publication across threads