Skip to content

Commit 5a974f6

Browse files
authored
Merge pull request #56 from FrangSierra/development
Add new methods from the new Firebase releases and update README
2 parents 50f6a4e + 4f2eb6e commit 5a974f6

File tree

5 files changed

+138
-56
lines changed

5 files changed

+138
-56
lines changed

README.md

Lines changed: 65 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ This repository started as a personal usage of [Nick Moskalenko](https://github.
1010

1111
```groovy
1212
dependencies {
13-
compile 'com.github.frangsierra:rx2firebase:1.4.0'
13+
compile 'com.github.frangsierra:rx2firebase:1.5.0'
1414
}
1515
```
1616
```
@@ -22,47 +22,13 @@ allprojects {
2222
}
2323
```
2424

25-
26-
## RxJava and RxJava 2.0
27-
One of the differences between RxJava and RxJava 2 is that RxJava 2 no longer accepts `null` values. Throwing a `NullPointerException` immediately. For this reason some of the methods of the library as been redesigned to return a `Completable` instead of a `Observable<Void>`. For example:
28-
29-
#### RxFirebase
30-
31-
```java
32-
@NonNull
33-
public static Observable<Void> updateEmail(@NonNull final FirebaseUser firebaseUser, @NonNull final String email) {
34-
return Observable.create(new Observable.OnSubscribe<Void>() {
35-
@Override
36-
public void call(final Subscriber<? super Void> subscriber) {
37-
RxHandler.assignOnTask(subscriber, firebaseUser.updateEmail(email));
38-
}
39-
});
40-
}
41-
```
42-
43-
#### Rx2Firebase
44-
45-
```java
46-
@NonNull
47-
public static Completable updateEmail(@NonNull final FirebaseUser firebaseUser, @NonNull final String email) {
48-
return Completable.create(new CompletableOnSubscribe() {
49-
@Override
50-
public void subscribe(CompletableEmitter emitter) throws Exception {
51-
RxCompletableHandler.assignOnTask(emitter, firebaseUser.updateEmail(email));
52-
}
53-
});
54-
}
55-
```
56-
57-
`RxCompletableHandler` manages the CompletableEmitters in the same way that `RxHandler` manages the `Subscriber`.
58-
You can check all the differences between RxJava and RxJava 2.0 in the next [Link](https://github.com/ReactiveX/RxJava/wiki/What's-different-in-2.0)
59-
6025
## Usage
6126
Library provides set of static methods of classes:
6227
* RxFirebaseAuth
6328
* RxFirebaseUser
6429
* RxFirebaseDatabase
6530
* RxFirebaseStorage
31+
* RxFirestore
6632

6733
It also provides a custom implementation of `FirebaseRecyclerAdapter`:
6834
* RxFirebaseRecyclerAdapter
@@ -78,6 +44,35 @@ Sign in with email and password:
7844
Log.i("Rxfirebase2", "User logged " + logged);
7945
});
8046
```
47+
### Firestore:
48+
49+
You can observe values providing the Class of expected data like:
50+
51+
```java
52+
DocumentReference document = firestore.collection("Users").document("UserId_1");
53+
RxFirestore.observeDocumentRef(document)
54+
.subscribe( userDoc -> {
55+
//Do something with my snapshot
56+
});
57+
```
58+
59+
Get and set documents on a specific reference:
60+
61+
```java
62+
DocumentReference document = firestore.collection("Users").document("UserId_1");
63+
User mynewUser = User("newUserName", 24);
64+
//Set data
65+
RxFirestore.setDocument(document, myNewUser).subscribe();
66+
//Get and map data
67+
RxFirestore.getDocument(document)
68+
.map( userDoc -> { return userDoc.toObject(User.class); })
69+
.subscribe( casterUser -> {
70+
//Do something with my already casted user
71+
});
72+
```
73+
74+
Finally you can do sync operations on the database using `runTransaction` and if you wanna realize multiple
75+
operations at once, you should use the method `atomicOperation` which wraps the `WriteBatch` related methods from Firestore.
8176

8277
### Database:
8378

@@ -250,6 +245,40 @@ public class PostAdapter extends RxFirebaseRecyclerAdapter<PostViewHolder, Post>
250245
}
251246
```
252247

248+
## RxJava and RxJava 2.0
249+
One of the differences between RxJava and RxJava 2 is that RxJava 2 no longer accepts `null` values. Throwing a `NullPointerException` immediately. For this reason some of the methods of the library as been redesigned to return a `Completable` instead of a `Observable<Void>`. For example:
250+
251+
#### RxFirebase
252+
253+
```java
254+
@NonNull
255+
public static Observable<Void> updateEmail(@NonNull final FirebaseUser firebaseUser, @NonNull final String email) {
256+
return Observable.create(new Observable.OnSubscribe<Void>() {
257+
@Override
258+
public void call(final Subscriber<? super Void> subscriber) {
259+
RxHandler.assignOnTask(subscriber, firebaseUser.updateEmail(email));
260+
}
261+
});
262+
}
263+
```
264+
265+
#### Rx2Firebase
266+
267+
```java
268+
@NonNull
269+
public static Completable updateEmail(@NonNull final FirebaseUser firebaseUser, @NonNull final String email) {
270+
return Completable.create(new CompletableOnSubscribe() {
271+
@Override
272+
public void subscribe(CompletableEmitter emitter) throws Exception {
273+
RxCompletableHandler.assignOnTask(emitter, firebaseUser.updateEmail(email));
274+
}
275+
});
276+
}
277+
```
278+
279+
`RxCompletableHandler` manages the CompletableEmitters in the same way that `RxHandler` manages the `Subscriber`.
280+
You can check all the differences between RxJava and RxJava 2.0 in the next [Link](https://github.com/ReactiveX/RxJava/wiki/What's-different-in-2.0)
281+
253282
## License
254283

255284
MIT License

app/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
buildscript {
22
ext {
33
rx_version = "2.1.10"
4-
rx_android_version = "2.0.1"
4+
rx_android_version = "2.0.2"
55
firebase_auth_version='15.1.0'
66
firebase_database_version='15.0.0'
77
firebase_storage_version='15.0.2'
@@ -20,7 +20,7 @@ android {
2020
}
2121

2222
compileSdkVersion 27
23-
buildToolsVersion "26.0.2"
23+
buildToolsVersion "26.0.3"
2424

2525
defaultConfig {
2626
minSdkVersion 14

app/src/main/java/durdinapps/rxfirebase2/RxFirebaseAuth.java

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
import com.google.firebase.auth.AuthCredential;
77
import com.google.firebase.auth.AuthResult;
88
import com.google.firebase.auth.FirebaseAuth;
9-
import com.google.firebase.auth.ProviderQueryResult;
9+
import com.google.firebase.auth.FirebaseUser;
10+
import com.google.firebase.auth.SignInMethodQueryResult;
1011

1112
import io.reactivex.Completable;
1213
import io.reactivex.CompletableEmitter;
@@ -143,16 +144,16 @@ public void subscribe(MaybeEmitter<AuthResult> emitter) throws Exception {
143144
*
144145
* @param firebaseAuth firebaseAuth instance.
145146
* @param email An email address.
146-
* @return a {@link Maybe} which emits an {@link ProviderQueryResult} if success.
147+
* @return a {@link Maybe} which emits an {@link SignInMethodQueryResult} if success.
147148
* @see <a href="https://firebase.google.com/docs/reference/android/com/google/firebase/auth/FirebaseAuth">Firebase Auth API</a>
148149
*/
149150
@NonNull
150-
public static Maybe<ProviderQueryResult> fetchProvidersForEmail(@NonNull final FirebaseAuth firebaseAuth,
151-
@NonNull final String email) {
152-
return Maybe.create(new MaybeOnSubscribe<ProviderQueryResult>() {
151+
public static Maybe<SignInMethodQueryResult> fetchSignInMethodsForEmail(@NonNull final FirebaseAuth firebaseAuth,
152+
@NonNull final String email) {
153+
return Maybe.create(new MaybeOnSubscribe<SignInMethodQueryResult>() {
153154
@Override
154-
public void subscribe(MaybeEmitter<ProviderQueryResult> emitter) throws Exception {
155-
RxHandler.assignOnTask(emitter, firebaseAuth.fetchProvidersForEmail(email));
155+
public void subscribe(MaybeEmitter<SignInMethodQueryResult> emitter) {
156+
RxHandler.assignOnTask(emitter, firebaseAuth.fetchSignInMethodsForEmail(email));
156157
}
157158
});
158159
}
@@ -179,6 +180,26 @@ public void subscribe(CompletableEmitter emitter) throws Exception {
179180
});
180181
}
181182

183+
/**
184+
* Asynchronously sets the provided user as currentUser on the current Auth instance. A new instance copy of the user provided will be made and set as currentUser.
185+
* <p>
186+
* This will trigger firebase.auth.Auth#onAuthStateChanged and firebase.auth.Auth#onIdTokenChanged listeners like other sign in methods.
187+
* @param firebaseAuth firebaseAuth instance.
188+
* @param newUser The new user to update the current instance.
189+
* @return a {@link Completable} which emits when the action is completed.
190+
* @see <a href="https://firebase.google.com/docs/reference/android/com/google/firebase/auth/FirebaseAuth">Firebase Auth API</a>
191+
*/
192+
@NonNull
193+
public static Completable updateCurrentUser(@NonNull final FirebaseAuth firebaseAuth,
194+
@NonNull final FirebaseUser newUser) {
195+
return Completable.create(new CompletableOnSubscribe() {
196+
@Override
197+
public void subscribe(CompletableEmitter emitter) throws Exception {
198+
RxCompletableHandler.assignOnTask(emitter, firebaseAuth.updateCurrentUser(newUser));
199+
}
200+
});
201+
}
202+
182203
/**
183204
* Observable which track the auth changes of {@link FirebaseAuth} to listen when an user is logged or not.
184205
*

app/src/main/java/durdinapps/rxfirebase2/RxFirestore.java

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,13 @@
1717
import com.google.firebase.firestore.FirebaseFirestoreException;
1818
import com.google.firebase.firestore.ListenerRegistration;
1919
import com.google.firebase.firestore.MetadataChanges;
20-
2120
import com.google.firebase.firestore.Query;
2221
import com.google.firebase.firestore.QuerySnapshot;
2322
import com.google.firebase.firestore.SetOptions;
2423
import com.google.firebase.firestore.Transaction;
2524
import com.google.firebase.firestore.WriteBatch;
2625

26+
import java.util.ArrayList;
2727
import java.util.List;
2828
import java.util.Map;
2929
import java.util.concurrent.Executor;
@@ -43,6 +43,7 @@
4343
import io.reactivex.SingleOnSubscribe;
4444
import io.reactivex.functions.Cancellable;
4545
import io.reactivex.functions.Function;
46+
import io.reactivex.schedulers.Schedulers;
4647

4748
import static durdinapps.rxfirebase2.DocumentSnapshotMapper.DOCUMENT_EXISTENCE_PREDICATE;
4849
import static durdinapps.rxfirebase2.DocumentSnapshotMapper.QUERY_EXISTENCE_PREDICATE;
@@ -82,6 +83,37 @@ public void subscribe(CompletableEmitter emitter) throws Exception {
8283
});
8384
}
8485

86+
/**
87+
* Execute all of the writes in this write batch as a single atomic unit.
88+
*
89+
* @param batches A list of write batched, used to perform multiple writes as a single atomic unit.
90+
*/
91+
public static Completable atomicOperation(@NonNull final List<WriteBatch> batches) {
92+
if (batches.isEmpty()) throw new IllegalArgumentException("Batches list can't be empty");
93+
94+
List<Completable> batchTasks = new ArrayList<>();
95+
for (final WriteBatch batch : batches) {
96+
batchTasks.add(Completable.create(new CompletableOnSubscribe() {
97+
@Override public void subscribe(final CompletableEmitter emitter) {
98+
batch.commit()
99+
.addOnSuccessListener(new OnSuccessListener<Void>() {
100+
@Override public void onSuccess(Void aVoid) {
101+
emitter.onComplete();
102+
}
103+
})
104+
.addOnFailureListener(new OnFailureListener() {
105+
@Override public void onFailure(@NonNull Exception e) {
106+
if (!emitter.isDisposed())
107+
emitter.onError(e);
108+
}
109+
});
110+
}
111+
}).subscribeOn(Schedulers.io()));
112+
}
113+
114+
return Completable.merge(batchTasks);
115+
}
116+
85117
/**
86118
* Adds a new document to this collection with the specified data, assigning it a document ID automatically.
87119
*

app/src/test/java/durdinapps/rxfirebase2/RxFirebaseAuthTest.java

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import com.google.firebase.auth.AuthResult;
88
import com.google.firebase.auth.FirebaseAuth;
99
import com.google.firebase.auth.FirebaseUser;
10-
import com.google.firebase.auth.ProviderQueryResult;
10+
import com.google.firebase.auth.SignInMethodQueryResult;
1111
import com.google.firebase.database.DataSnapshot;
1212

1313
import org.junit.Before;
@@ -43,7 +43,7 @@ public class RxFirebaseAuthTest {
4343
private Task<AuthResult> authResultTask;
4444

4545
@Mock
46-
private Task<ProviderQueryResult> providerQueryResultTask;
46+
private Task<SignInMethodQueryResult> providerQueryResultTask;
4747

4848
@Mock
4949
private Task<ActionCodeResult> actionCodeResultTask;
@@ -58,7 +58,7 @@ public class RxFirebaseAuthTest {
5858
private AuthResult authResult;
5959

6060
@Mock
61-
private ProviderQueryResult providerQueryResult;
61+
private SignInMethodQueryResult providerQueryResult;
6262

6363
@Mock
6464
private ActionCodeResult actionCodeResult;
@@ -88,7 +88,7 @@ public void setup() {
8888
when(firebaseAuth.signInWithCredential(authCredential)).thenReturn(authResultTask);
8989
when(firebaseAuth.signInWithCustomToken(ANY_TOKEN)).thenReturn(authResultTask);
9090
when(firebaseAuth.createUserWithEmailAndPassword(ANY_EMAIL, ANY_PASSWORD)).thenReturn(authResultTask);
91-
when(firebaseAuth.fetchProvidersForEmail(ANY_EMAIL)).thenReturn(providerQueryResultTask);
91+
when(firebaseAuth.fetchSignInMethodsForEmail(ANY_EMAIL)).thenReturn(providerQueryResultTask);
9292
when(firebaseAuth.checkActionCode(ANY_CODE)).thenReturn(actionCodeResultTask);
9393
when(firebaseAuth.verifyPasswordResetCode(ANY_CODE)).thenReturn(checkCodeResultTask);
9494
when(firebaseAuth.sendPasswordResetEmail(ANY_EMAIL)).thenReturn(voidTask);
@@ -275,14 +275,14 @@ public void signInWithCustomTokenError() throws InterruptedException {
275275
@Test
276276
public void fetchProvidersForEmail() throws InterruptedException {
277277

278-
TestObserver<ProviderQueryResult> authTestObserver = RxFirebaseAuth
279-
.fetchProvidersForEmail(firebaseAuth, ANY_EMAIL)
278+
TestObserver<SignInMethodQueryResult> authTestObserver = RxFirebaseAuth
279+
.fetchSignInMethodsForEmail(firebaseAuth, ANY_EMAIL)
280280
.test();
281281

282282
testOnSuccessListener.getValue().onSuccess(providerQueryResult);
283283
testOnCompleteListener.getValue().onComplete(providerQueryResultTask);
284284

285-
verify(firebaseAuth).fetchProvidersForEmail(eq(ANY_EMAIL));
285+
verify(firebaseAuth).fetchSignInMethodsForEmail(eq(ANY_EMAIL));
286286

287287
authTestObserver.assertNoErrors()
288288
.assertValueCount(1)
@@ -313,13 +313,13 @@ public void checkActionCode() throws InterruptedException {
313313
@Test
314314
public void fetchProvidersForEmailError() throws InterruptedException {
315315

316-
TestObserver<ProviderQueryResult> authTestObserver = RxFirebaseAuth
317-
.fetchProvidersForEmail(firebaseAuth, ANY_EMAIL)
316+
TestObserver<SignInMethodQueryResult> authTestObserver = RxFirebaseAuth
317+
.fetchSignInMethodsForEmail(firebaseAuth, ANY_EMAIL)
318318
.test();
319319

320320
testOnFailureListener.getValue().onFailure(EXCEPTION);
321321

322-
verify(firebaseAuth).fetchProvidersForEmail(ANY_EMAIL);
322+
verify(firebaseAuth).fetchSignInMethodsForEmail(ANY_EMAIL);
323323

324324
authTestObserver.assertError(EXCEPTION)
325325
.assertNotComplete()

0 commit comments

Comments
 (0)