1 /*
2  * Copyright 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package androidx.paging
18 
19 import kotlin.jvm.JvmOverloads
20 import kotlin.jvm.JvmStatic
21 import kotlinx.coroutines.flow.Flow
22 import kotlinx.coroutines.flow.flowOf
23 
24 /**
25  * Container for Paged data from a single generation of loads.
26  *
27  * Each refresh of data (generally either pushed by local storage, or pulled from the network) will
28  * have a separate corresponding [PagingData].
29  */
30 public class PagingData<T : Any>
31 internal constructor(
32     internal val flow: Flow<PageEvent<T>>,
33     internal val uiReceiver: UiReceiver,
34     internal val hintReceiver: HintReceiver,
35 
36     /**
37      * A lambda returning a nullable PageEvent.Insert containing data which can be accessed and
38      * displayed synchronously without requiring collection.
39      *
40      * For example, the data may be real loaded data that has been cached via [cachedIn].
41      */
<lambda>null42     private val cachedPageEvent: () -> PageEvent.Insert<T>? = { null }
43 ) {
44     public companion object {
45         internal val NOOP_UI_RECEIVER =
46             object : UiReceiver {
retrynull47                 override fun retry() {}
48 
refreshnull49                 override fun refresh() {}
50             }
51 
52         internal val NOOP_HINT_RECEIVER =
53             object : HintReceiver {
accessHintnull54                 override fun accessHint(viewportHint: ViewportHint) {}
55             }
56 
57         /**
58          * Create a [PagingData] that immediately displays an empty list of items when submitted to
59          * a presenter. E.g., [AsyncPagingDataAdapter][androidx.paging.AsyncPagingDataAdapter] and
60          * dispatches [LoadState.NotLoading] on all LoadStates to the presenter.
61          */
62         @Suppress("UNCHECKED_CAST")
63         @JvmStatic // Convenience for Java developers.
emptynull64         public fun <T : Any> empty(): PagingData<T> =
65             PagingData(
66                 flow =
67                     flowOf(
68                         PageEvent.StaticList(
69                             data = listOf(),
70                             sourceLoadStates = null,
71                             mediatorLoadStates = null,
72                         )
73                     ),
74                 uiReceiver = NOOP_UI_RECEIVER,
75                 hintReceiver = NOOP_HINT_RECEIVER,
76                 cachedPageEvent = {
77                     PageEvent.Insert.Refresh(
78                         pages =
79                             listOf(
80                                 TransformablePage(
81                                     originalPageOffset = 0,
82                                     data = listOf(),
83                                 )
84                             ),
85                         placeholdersBefore = 0,
86                         placeholdersAfter = 0,
87                         sourceLoadStates = LoadStates.IDLE,
88                         mediatorLoadStates = null
89                     )
90                 }
91             )
92 
93         /**
94          * Create a [PagingData] that immediately displays an empty list of items when submitted to
95          * a presenter. E.g., [AsyncPagingDataAdapter][androidx.paging.AsyncPagingDataAdapter].
96          *
97          * @param sourceLoadStates [LoadStates] of [PagingSource] to pass forward to a presenter.
98          *   E.g., [AsyncPagingDataAdapter][androidx.paging.AsyncPagingDataAdapter].
99          * @param mediatorLoadStates [LoadStates] of [RemoteMediator] to pass forward to a
100          *   presenter. E.g., [AsyncPagingDataAdapter][androidx.paging.AsyncPagingDataAdapter].
101          */
102         @Suppress("UNCHECKED_CAST")
103         @JvmOverloads
104         @JvmStatic // Convenience for Java developers.
emptynull105         public fun <T : Any> empty(
106             sourceLoadStates: LoadStates,
107             mediatorLoadStates: LoadStates? = null,
108         ): PagingData<T> =
109             PagingData(
110                 flow =
111                     flowOf(
112                         PageEvent.StaticList(
113                             data = listOf(),
114                             sourceLoadStates = sourceLoadStates,
115                             mediatorLoadStates = mediatorLoadStates,
116                         )
117                     ),
118                 uiReceiver = NOOP_UI_RECEIVER,
119                 hintReceiver = NOOP_HINT_RECEIVER,
120                 cachedPageEvent = {
121                     PageEvent.Insert.Refresh(
122                         pages =
123                             listOf(
124                                 TransformablePage(
125                                     originalPageOffset = 0,
126                                     data = listOf(),
127                                 )
128                             ),
129                         placeholdersBefore = 0,
130                         placeholdersAfter = 0,
131                         sourceLoadStates = sourceLoadStates,
132                         mediatorLoadStates = mediatorLoadStates
133                     )
134                 }
135             )
136 
137         /**
138          * Create a [PagingData] that immediately displays a static list of items when submitted to
139          * a presenter. E.g., [AsyncPagingDataAdapter][androidx.paging.AsyncPagingDataAdapter] and
140          * dispatches [LoadState.NotLoading] on all LoadStates to the presenter.
141          *
142          * @param data Static list of [T] to display.
143          */
144         @JvmStatic // Convenience for Java developers.
fromnull145         public fun <T : Any> from(
146             data: List<T>,
147         ): PagingData<T> =
148             PagingData(
149                 flow =
150                     flowOf(
151                         PageEvent.StaticList(
152                             data = data,
153                             sourceLoadStates = null,
154                             mediatorLoadStates = null,
155                         )
156                     ),
157                 uiReceiver = NOOP_UI_RECEIVER,
158                 hintReceiver = NOOP_HINT_RECEIVER,
159                 cachedPageEvent = {
160                     PageEvent.Insert.Refresh(
161                         pages = listOf(TransformablePage(0, data)),
162                         placeholdersBefore = 0,
163                         placeholdersAfter = 0,
164                         sourceLoadStates = LoadStates.IDLE,
165                         mediatorLoadStates = null
166                     )
167                 }
168             )
169 
170         /**
171          * Create a [PagingData] that immediately displays a static list of items when submitted to
172          * a presenter. E.g., [AsyncPagingDataAdapter][androidx.paging.AsyncPagingDataAdapter].
173          *
174          * @param data Static list of [T] to display.
175          * @param sourceLoadStates [LoadStates] of [PagingSource] to pass forward to a presenter.
176          *   E.g., [AsyncPagingDataAdapter][androidx.paging.AsyncPagingDataAdapter].
177          * @param mediatorLoadStates [LoadStates] of [RemoteMediator] to pass forward to a
178          *   presenter. E.g., [AsyncPagingDataAdapter][androidx.paging.AsyncPagingDataAdapter].
179          */
180         @JvmOverloads
181         @JvmStatic // Convenience for Java developers.
fromnull182         public fun <T : Any> from(
183             data: List<T>,
184             sourceLoadStates: LoadStates,
185             mediatorLoadStates: LoadStates? = null,
186         ): PagingData<T> =
187             PagingData(
188                 flow =
189                     flowOf(
190                         PageEvent.StaticList(
191                             data = data,
192                             sourceLoadStates = sourceLoadStates,
193                             mediatorLoadStates = mediatorLoadStates,
194                         )
195                     ),
196                 uiReceiver = NOOP_UI_RECEIVER,
197                 hintReceiver = NOOP_HINT_RECEIVER,
198                 cachedPageEvent = {
199                     PageEvent.Insert.Refresh(
200                         pages = listOf(TransformablePage(0, data)),
201                         placeholdersBefore = 0,
202                         placeholdersAfter = 0,
203                         sourceLoadStates = sourceLoadStates,
204                         mediatorLoadStates = mediatorLoadStates
205                     )
206                 }
207             )
208     }
209 
cachedEventnull210     internal fun cachedEvent(): PageEvent.Insert<T>? = cachedPageEvent()
211 }
212