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 androidx.paging.PagingSource.LoadResult.Page 20 21 /** Load access information blob, containing information from presenter. */ 22 internal sealed class ViewportHint( 23 /** 24 * Number of loaded items presented before this hint. Calculated as the distance from this hint 25 * to first loaded item being presented: `anchorPosition - firstLoadedItemPosition` 26 * 27 * Zero indicates access at boundary Positive -> Within loaded range or in placeholders after 28 * presented items if greater than the size of all presented items. Negative -> placeholder 29 * access before first loaded item. 30 */ 31 val presentedItemsBefore: Int, 32 /** 33 * Number of loaded items presented after this hint. Calculated as the distance from this hint 34 * to last loaded item being presented: `presenterSize - anchorPosition - placeholdersAfter - 1` 35 * 36 * Zero indicates access at boundary Positive -> Within loaded range or in placeholders before 37 * presented items if greater than the size of all presented items. Negative -> placeholder 38 * access after last loaded item. 39 */ 40 val presentedItemsAfter: Int, 41 /** 42 * [hintOriginalPageOffset][TransformablePage.hintOriginalPageOffset] of the first presented 43 * [TransformablePage] when this [ViewportHint] was created. 44 */ 45 val originalPageOffsetFirst: Int, 46 /** 47 * [hintOriginalPageOffset][TransformablePage.hintOriginalPageOffset] of the last presented 48 * [TransformablePage] when this [ViewportHint] was created. 49 */ 50 val originalPageOffsetLast: Int, 51 ) { equalsnull52 override fun equals(other: Any?): Boolean { 53 if (this === other) return true 54 if (other !is ViewportHint) return false 55 56 return presentedItemsBefore == other.presentedItemsBefore && 57 presentedItemsAfter == other.presentedItemsAfter && 58 originalPageOffsetFirst == other.originalPageOffsetFirst && 59 originalPageOffsetLast == other.originalPageOffsetLast 60 } 61 62 /** 63 * @return Count of presented items between this hint, and either: 64 * * the beginning of the list if [loadType] == PREPEND 65 * * the end of the list if loadType == APPEND 66 */ presentedItemsBeyondAnchornull67 internal fun presentedItemsBeyondAnchor(loadType: LoadType): Int = 68 when (loadType) { 69 LoadType.REFRESH -> 70 throw IllegalArgumentException("Cannot get presentedItems for loadType: REFRESH") 71 LoadType.PREPEND -> presentedItemsBefore 72 LoadType.APPEND -> presentedItemsAfter 73 } 74 hashCodenull75 override fun hashCode(): Int { 76 return presentedItemsBefore.hashCode() + 77 presentedItemsAfter.hashCode() + 78 originalPageOffsetFirst.hashCode() + 79 originalPageOffsetLast.hashCode() 80 } 81 82 /** 83 * [ViewportHint] reporting presenter state after receiving initial page. An [Initial] hint 84 * should never take precedence over an [Access] hint and is only used to inform [PageFetcher] 85 * how many items from the initial page load were presented by [PagingDataPresenter] 86 */ 87 class Initial( 88 presentedItemsBefore: Int, 89 presentedItemsAfter: Int, 90 originalPageOffsetFirst: Int, 91 originalPageOffsetLast: Int 92 ) : 93 ViewportHint( 94 presentedItemsBefore = presentedItemsBefore, 95 presentedItemsAfter = presentedItemsAfter, 96 originalPageOffsetFirst = originalPageOffsetFirst, 97 originalPageOffsetLast = originalPageOffsetLast, 98 ) { toStringnull99 override fun toString(): String { 100 return """ViewportHint.Initial( 101 | presentedItemsBefore=$presentedItemsBefore, 102 | presentedItemsAfter=$presentedItemsAfter, 103 | originalPageOffsetFirst=$originalPageOffsetFirst, 104 | originalPageOffsetLast=$originalPageOffsetLast, 105 |)""" 106 .trimMargin() 107 } 108 } 109 110 /** 111 * [ViewportHint] representing an item access that should be used to trigger loads to fulfill 112 * prefetch distance. 113 */ 114 class Access( 115 /** Page index offset from initial load */ 116 val pageOffset: Int, 117 /** 118 * Original index of item in the [Page] with [pageOffset]. 119 * 120 * Three cases to consider: 121 * - [indexInPage] in Page.data.indices -> Hint references original item directly 122 * - [indexInPage] > Page.data.indices -> Hint references a placeholder after the last 123 * presented item. 124 * - [indexInPage] < 0 -> Hint references a placeholder before the first presented item. 125 */ 126 val indexInPage: Int, 127 presentedItemsBefore: Int, 128 presentedItemsAfter: Int, 129 originalPageOffsetFirst: Int, 130 originalPageOffsetLast: Int 131 ) : 132 ViewportHint( 133 presentedItemsBefore = presentedItemsBefore, 134 presentedItemsAfter = presentedItemsAfter, 135 originalPageOffsetFirst = originalPageOffsetFirst, 136 originalPageOffsetLast = originalPageOffsetLast, 137 ) { equalsnull138 override fun equals(other: Any?): Boolean { 139 if (this === other) return true 140 if (other !is Access) return false 141 142 return pageOffset == other.pageOffset && 143 indexInPage == other.indexInPage && 144 presentedItemsBefore == other.presentedItemsBefore && 145 presentedItemsAfter == other.presentedItemsAfter && 146 originalPageOffsetFirst == other.originalPageOffsetFirst && 147 originalPageOffsetLast == other.originalPageOffsetLast 148 } 149 hashCodenull150 override fun hashCode(): Int { 151 return super.hashCode() + pageOffset.hashCode() + indexInPage.hashCode() 152 } 153 toStringnull154 override fun toString(): String { 155 return """ViewportHint.Access( 156 | pageOffset=$pageOffset, 157 | indexInPage=$indexInPage, 158 | presentedItemsBefore=$presentedItemsBefore, 159 | presentedItemsAfter=$presentedItemsAfter, 160 | originalPageOffsetFirst=$originalPageOffsetFirst, 161 | originalPageOffsetLast=$originalPageOffsetLast, 162 |)""" 163 .trimMargin() 164 } 165 } 166 } 167