@@ -12,9 +12,13 @@ Before using this library, you should be familiar with the following topics:
12
12
1 . [ Data model] ( #data-model )
13
13
1 . [ Querying] ( #querying )
14
14
1 . [ Populating a RecyclerView] ( #using-firebaseui-to-populate-a-recyclerview )
15
- 1 . [ Using the adapter] ( #using-the-firestorerecycleradapter )
16
- 1 . [ Adapter lifecyle] ( #firestorerecycleradapter-lifecycle )
17
- 1 . [ Events] ( #data-and-error-events )
15
+ 1 . [ Choosing an adapter] ( #choosing-an-adapter )
16
+ 1 . [ Using the FirestoreRecyclerAdapter] ( #using-the-firestorerecycleradapter )
17
+ 1 . [ Adapter lifecyle] ( #firestorerecycleradapter-lifecycle )
18
+ 1 . [ Events] ( #data-and-error-events )
19
+ 1 . [ Using the FirestoreRecyclerAdapter] ( #using-the-firestorepagingadapter )
20
+ 1 . [ Adapter lifecyle] ( #firestorepagingadapter-lifecycle )
21
+ 1 . [ Events] ( #paging-events )
18
22
19
23
## Data model
20
24
@@ -109,6 +113,18 @@ updates with the `EventListener` on the `Query`.
109
113
110
114
Fear not, FirebaseUI does all of this for you automatically!
111
115
116
+
117
+ ### Choosing an adapter
118
+
119
+ FirebaseUI offers two types of RecyclerView adapters for Cloud Firestore:
120
+
121
+ * ` FirestoreRecyclerAdapter ` - bind a ` Query ` to a ` RecyclerView ` and respond to all real-time
122
+ events included items being added, removed, moved, or changed. Best used with small result sets
123
+ since all results are loaded at once.
124
+ * ` FirestorePagingAdapter ` - bind a ` Query ` to a ` RecyclerView ` by loading data in pages. Best
125
+ used with large, static data sets. Real-time events are not respected by this adapter, so it
126
+ will not detect new/removed items or changes to items already loaded.
127
+
112
128
### Using the ` FirestoreRecyclerAdapter `
113
129
114
130
The ` FirestoreRecyclerAdapter ` binds a ` Query ` to a ` RecyclerView ` . When documents are added,
@@ -164,9 +180,9 @@ FirestoreRecyclerAdapter adapter = new FirestoreRecyclerAdapter<Chat, ChatHolder
164
180
Finally attach the adapter to your ` RecyclerView ` with the ` RecyclerView#setAdapter() ` .
165
181
Don't forget to also set a ` LayoutManager ` !
166
182
167
- ### ` FirestoreRecyclerAdapter ` lifecycle
183
+ #### ` FirestoreRecyclerAdapter ` lifecycle
168
184
169
- #### Start/stop listening
185
+ ##### Start/stop listening
170
186
171
187
The ` FirestoreRecyclerAdapter ` uses a snapshot listener to monitor changes to the Firestore query.
172
188
To begin listening for data, call the ` startListening() ` method. You may want to call this
@@ -192,15 +208,15 @@ protected void onStop() {
192
208
}
193
209
```
194
210
195
- #### Automatic listening
211
+ ##### Automatic listening
196
212
197
213
If you don't want to manually start/stop listening you can use
198
214
[ Android Architecture Components] [ arch-components ] to automatically manage the lifecycle of the
199
215
` FirestoreRecyclerAdapter ` . Pass a ` LifecycleOwner ` to
200
216
` FirestoreRecyclerOptions.Builder#setLifecycleOwner(...) ` and FirebaseUI will automatically
201
217
start and stop listening in ` onStart() ` and ` onStop() ` .
202
218
203
- ### Data and error events
219
+ #### Data and error events
204
220
205
221
When using the ` FirestoreRecyclerAdapter ` you may want to perform some action every time data
206
222
changes or when there is an error. To do this, override the ` onDataChanged() ` and ` onError() `
@@ -227,7 +243,155 @@ FirestoreRecyclerAdapter adapter = new FirestoreRecyclerAdapter<Chat, ChatHolder
227
243
```
228
244
229
245
246
+ ### Using the ` FirestorePagingAdapter `
247
+
248
+ The ` FirestorePagingAdapter ` binds a ` Query ` to a ` RecyclerView ` by loading documents in pages.
249
+ This results in a time and memory efficient binding, however it gives up the real-time events
250
+ afforted by the ` FirestoreRecyclerAdaoter ` .
251
+
252
+ The ` FirestorePagingAdapter ` is built on top of the [ Android Paging Support Library] [ paging-support ] .
253
+ Before using the adapter in your application, you must add a dependency on the support library:
254
+
255
+ ``` groovy
256
+ implementation 'android.arch.paging:runtime:1.0.0-beta1'
257
+ ```
258
+
259
+ First, configure the adapter by building ` FirestorePagingOptions ` . Since the paging adapter
260
+ is not appropriate for a chat application (it would not detect new messages), we will consider
261
+ an adapter that loads a generic ` Item ` :
262
+
263
+ ``` java
264
+ // The "base query" is a query with no startAt/endAt/limit clauses that the adapter can use
265
+ // to form smaller queries for each page. It should only include where() and orderBy() clauses
266
+ Query baseQuery = mItemsCollection. orderBy(" value" , Query . Direction . ASCENDING );
267
+
268
+ // This configuration comes from the Paging Support Library
269
+ // https://developer.android.com/reference/android/arch/paging/PagedList.Config.html
270
+ PagedList . Config config = new PagedList .Config .Builder ()
271
+ .setEnablePlaceholders(false )
272
+ .setPrefetchDistance(10 )
273
+ .setPageSize(20 )
274
+ .build();
275
+
276
+ // The options for the adapter combine the paging configuration with query information
277
+ // and application-specific options for lifecycle, etc.
278
+ FirestorePagingOptions<Item > options = new FirestorePagingOptions .Builder<Item > ()
279
+ .setLifecycleOwner(this )
280
+ .setQuery(baseQuery, config, Item . class)
281
+ .build();
282
+ ```
283
+
284
+ If you need to customize how your model class is parsed, you can use a custom ` SnapshotParser ` :
285
+
286
+ ``` java
287
+ .. . setQuery(... , new SnapshotParser<Item > () {
288
+ @NonNull
289
+ @Override
290
+ public Item parseSnapshot (@NonNull DocumentSnapshot snapshot ) {
291
+ return ... ;
292
+ }
293
+ });
294
+ ```
295
+
296
+ Next create the ` FirestorePagingAdapter ` object. You should already have a ` ViewHolder ` subclass
297
+ for displaying each item. In this case we will use a custom ` ItemViewHolder ` class:
298
+
299
+ ``` java
300
+ FirestorePagingAdapter<Item , ItemViewHolder > adapter =
301
+ new FirestorePagingAdapter<Item , ItemViewHolder > (options) {
302
+ @NonNull
303
+ @Override
304
+ public ItemViewHolder onCreateViewHolder (@NonNull ViewGroup parent , int viewType ) {
305
+ // Create the ItemViewHolder
306
+ // ,,,
307
+ }
308
+
309
+ @Override
310
+ protected void onBindViewHolder (@NonNull ItemViewHolder holder ,
311
+ int position ,
312
+ @NonNull Item model ) {
313
+ // Bind the item to the view holder
314
+ // ...
315
+ }
316
+ };
317
+ ```
318
+
319
+ Finally attach the adapter to your ` RecyclerView ` with the ` RecyclerView#setAdapter() ` .
320
+ Don't forget to also set a ` LayoutManager ` !
321
+
322
+ #### ` FirestorePagingAdapter ` lifecycle
323
+
324
+ ##### Start/stop listening
325
+
326
+ The ` FirestorePagingAdapter ` listens for scrolling events and loads additional pages from the
327
+ database only when needed.
328
+
329
+ To begin populating data, call the ` startListening() ` method. You may want to call this
330
+ in your ` onStart() ` method. Make sure you have finished any authentication necessary to read the
331
+ data before calling ` startListening() ` or your query will fail.
332
+
333
+ ``` java
334
+ @Override
335
+ protected void onStart() {
336
+ super . onStart();
337
+ adapter. startListening();
338
+ }
339
+ ```
340
+
341
+ Similarly, the ` stopListening() ` call removes the snapshot listener and all data in the adapter.
342
+ Call this method when the containing Activity or Fragment stops:
343
+
344
+ ``` java
345
+ @Override
346
+ protected void onStop() {
347
+ super . onStop();
348
+ adapter. stopListening();
349
+ }
350
+ ```
351
+
352
+ ##### Automatic listening
353
+
354
+ If you don't want to manually start/stop listening you can use
355
+ [ Android Architecture Components] [ arch-components ] to automatically manage the lifecycle of the
356
+ ` FirestorePagingAdapter ` . Pass a ` LifecycleOwner ` to
357
+ ` FirestorePagingOptions.Builder#setLifecycleOwner(...) ` and FirebaseUI will automatically
358
+ start and stop listening in ` onStart() ` and ` onStop() ` .
359
+
360
+ #### Paging events
361
+
362
+ When using the ` FirestorePagingAdapter ` you may want to perform some action every time data
363
+ changes or when there is an error. To do this, override the ` onLoadingStateChanged() `
364
+ method of the adapter:
365
+
366
+ ``` java
367
+ FirestorePagingAdapter<Item , ItemViewHolder > adapter =
368
+ new FirestorePagingAdapter<Item , ItemViewHolder > (options) {
369
+
370
+ // ...
371
+
372
+ @Override
373
+ protected void onLoadingStateChanged (@NonNull LoadingState state ) {
374
+ switch (state) {
375
+ case LOADING_INITIAL :
376
+ // The initial load has begun
377
+ // ...
378
+ case LOADING_MORE :
379
+ // The adapter has started to load an additional page
380
+ // ...
381
+ case LOADED :
382
+ // The previous load (either initial or additional) completed
383
+ // ...
384
+ case ERROR :
385
+ // The previous load (either initial or additional) failed. Call
386
+ // the retry() method in order to retry the load operation.
387
+ // ...
388
+ }
389
+ }
390
+ };
391
+ ```
392
+
230
393
[ firestore-docs ] : https://firebase.google.com/docs/firestore/
231
394
[ firestore-custom-objects ] : https://firebase.google.com/docs/firestore/manage-data/add-data#custom_objects
232
395
[ recyclerview ] : https://developer.android.com/reference/android/support/v7/widget/RecyclerView.html
233
396
[ arch-components ] : https://developer.android.com/topic/libraries/architecture/index.html
397
+ [ paging-support ] : https://developer.android.com/topic/libraries/architecture/paging.html
0 commit comments