1# @ohos.arkui.Prefetcher (Prefetching) 2Used in conjunction with **LazyForEach**, the **Prefetcher** module provides content prefetching capabilities for container components such as **List**, **Grid**, **Waterfall**, and **Swiper** during scrolling, to enhance the user browsing experience. 3 4> **NOTE** 5> 6> The initial APIs of this module are supported since API version 12. Updates will be marked with a superscript to indicate their earliest API version. 7 8## Modules to Import 9 10```ts 11import { BasicPrefetcher, IDataSourcePrefetching, IPrefetcher } from '@kit.ArkUI'; 12``` 13 14 15## IPrefetcher 16Implement this API to provide prefetching capabilities. 17 18**Atomic service API**: This API can be used in atomic services since API version 12. 19 20**System capability**: SystemCapability.ArkUI.ArkUI.Full 21 22### setDataSource 23setDataSource(dataSource: IDataSourcePrefetching): void; 24 25Sets the prefetching-capable data source to bind to the **Prefetcher** object. 26 27**Atomic service API**: This API can be used in atomic services since API version 12. 28 29**System capability**: SystemCapability.ArkUI.ArkUI.Full 30 31**Parameters** 32 33| Name | Type | Mandatory| Description | 34|------------|---------------------------------------------------|----|------------| 35| dataSource | [IDataSourcePrefetching](#idatasourceprefetching) | Yes | Prefetching-capable data source.| 36 37```typescript 38class MyPrefetcher implements IPrefetcher { 39 private dataSource?: IDataSourcePrefetching; 40 41 setDataSource(dataSource: IDataSourcePrefetching): void { 42 this.dataSource = dataSource; 43 } 44 45 visibleAreaChanged(minVisible: number, maxVisible: number): void { 46 this.dataSource?.prefetch(minVisible); 47 } 48} 49``` 50 51### visibleAreaChanged 52visibleAreaChanged(minVisible: number, maxVisible: number): void 53 54Called when the boundaries of the visible area change. It works with the **List**, **Grid**, **Waterfall**, and **Swiper** components. 55 56**Atomic service API**: This API can be used in atomic services since API version 12. 57 58**System capability**: SystemCapability.ArkUI.ArkUI.Full 59 60**Parameters** 61 62| Name | Type | Mandatory| Description | 63|------------|--------|----|-----------| 64| minVisible | number | Yes | Upper bound of the visible area.| 65| maxVisible | number | Yes | Lower bound of the visible area.| 66 67```typescript 68class MyPrefetcher implements IPrefetcher { 69 private dataSource?: IDataSourcePrefetching; 70 71 setDataSource(dataSource: IDataSourcePrefetching): void { 72 this.dataSource = dataSource; 73 } 74 75 visibleAreaChanged(minVisible: number, maxVisible: number): void { 76 this.dataSource?.prefetch(minVisible); 77 } 78} 79``` 80 81## BasicPrefetcher 82As a fundamental implementation of **IPrefetcher**, offers an intelligent data prefetching algorithm that decides which data items to prefetch based on real-time changes in the visible area on the screen and variations in the prefetch duration. It can also determine which prefetch requests should be canceled based on the user's scrolling actions. 83 84**Atomic service API**: This API can be used in atomic services since API version 12. 85 86**System capability**: SystemCapability.ArkUI.ArkUI.Full 87 88### constructor 89constructor(dataSource?: IDataSourcePrefetching) 90 91A constructor used to create a **DataSource** instance. 92 93**Atomic service API**: This API can be used in atomic services since API version 12. 94 95**System capability**: SystemCapability.ArkUI.ArkUI.Full 96 97**Parameters** 98 99| Name | Type | Mandatory| Description | 100|------------|---------------------------------------------------|----|------------| 101| dataSource | [IDataSourcePrefetching](#idatasourceprefetching) | No | Prefetching-capable data source.| 102 103### setDataSource 104setDataSource(dataSource: IDataSourcePrefetching): void; 105 106Sets the prefetching-capable data source to bind to the **Prefetcher** object. 107 108**Atomic service API**: This API can be used in atomic services since API version 12. 109 110**System capability**: SystemCapability.ArkUI.ArkUI.Full 111 112**Parameters** 113 114| Name | Type | Mandatory| Description | 115|------------|---------------------------------------------------|----|------------| 116| dataSource | [IDataSourcePrefetching](#idatasourceprefetching) | Yes | Prefetching-capable data source.| 117 118### visibleAreaChanged 119visibleAreaChanged(minVisible: number, maxVisible: number): void 120 121Called when the boundaries of the visible area change. It works with the **List**, **Grid**, **Waterfall**, and **Swiper** components. 122 123**Atomic service API**: This API can be used in atomic services since API version 12. 124 125**System capability**: SystemCapability.ArkUI.ArkUI.Full 126 127**Parameters** 128 129| Name | Type | Mandatory| Description | 130|------------|--------|----|-----------| 131| minVisible | number | Yes | Upper bound of the visible area.| 132| maxVisible | number | Yes | Lower bound of the visible area.| 133 134## IDataSourcePrefetching 135 136Implements a prefetching-capable data source. 137 138**Atomic service API**: This API can be used in atomic services since API version 12. 139 140**System capability**: SystemCapability.ArkUI.ArkUI.Full 141 142### prefetch 143**Atomic service API**: This API can be used in atomic services since API version 12. 144 145**System capability**: SystemCapability.ArkUI.ArkUI.Full 146 147**Parameters** 148 149| Name | Type | Mandatory| Description | 150|-------|--------|----|----------| 151| index | number | Yes | Index of the data item to be prefetched.| 152 153### cancel 154**Atomic service API**: This API can be used in atomic services since API version 12. 155 156**System capability**: SystemCapability.ArkUI.ArkUI.Full 157 158**Parameters** 159 160| Name | Type | Mandatory| Description | 161|-------|--------|----|------------| 162| index | number | Yes | Index of the data item whose prefetching should be canceled.| 163 164When list content moves off the screen (for example, during fast scrolling scenarios), once the prefetching algorithm determines which items outside the screen can have their prefetching canceled, this API is called. For instance, if the HTTP framework supports request cancellation, network requests initiated in the **prefetch** API can be canceled here. 165 166## Example 167 168```typescript 169import { BasicPrefetcher, IDataSourcePrefetching } from '@kit.ArkUI'; 170import { image } from '@kit.ImageKit'; 171 172const ITEMS_ON_SCREEN = 8; 173 174@Entry 175@Component 176struct PrefetcherDemoComponent { 177 private readonly dataSource = new MyDataSource(2000, 500); 178 private readonly prefetcher = new BasicPrefetcher(this.dataSource); 179 180 build() { 181 Column() { 182 List() { 183 LazyForEach(this.dataSource, (item: PictureItem) => { 184 ListItem() { 185 PictureItemComponent({ info: item }) 186 .height(`${100 / ITEMS_ON_SCREEN}%`) 187 } 188 }, (item: PictureItem) => item.title) 189 } 190 .onScrollIndex((start: number, end: number) => { 191 this.prefetcher.visibleAreaChanged(start, end); 192 }) 193 } 194 } 195} 196 197@Component 198struct PictureItemComponent { 199 @ObjectLink info: PictureItem; 200 201 build() { 202 Row() { 203 Image(this.info.imagePixelMap) 204 .objectFit(ImageFit.Contain) 205 .width('40%') 206 Text(this.info.title) 207 .width('60%') 208 } 209 } 210} 211 212@Observed 213class PictureItem { 214 readonly color: number; 215 title: string; 216 imagePixelMap: image.PixelMap | undefined; 217 key: string; 218 219 constructor(color: number, title: string) { 220 this.color = color; 221 this.title = title; 222 this.key = title; 223 } 224} 225 226type ItemIndex = number; 227type TimerId = number; 228 229class MyDataSource implements IDataSourcePrefetching { 230 private readonly items: PictureItem[]; 231 private readonly fetchDelayMs: number; 232 private readonly fetches: Map<ItemIndex, TimerId> = new Map(); 233 234 constructor(numItems: number, fetchDelayMs: number) { 235 this.items = []; 236 this.fetchDelayMs = fetchDelayMs; 237 for (let i = 0; i < numItems; i++) { 238 const item = new PictureItem(getRandomColor(), `Item ${i}`) 239 this.items.push(item); 240 } 241 } 242 243 async prefetch(index: number): Promise<void> { 244 const item = this.items[index]; 245 if (item.imagePixelMap) { 246 return; 247 } 248 249 // Perform time-consuming operations. 250 return new Promise<void>(resolve => { 251 const timeoutId = setTimeout(async () => { 252 this.fetches.delete(index); 253 const bitmap = create10x10Bitmap(item.color); 254 const imageSource: image.ImageSource = image.createImageSource(bitmap); 255 item.imagePixelMap = await imageSource.createPixelMap(); 256 resolve(); 257 }, this.fetchDelayMs); 258 259 this.fetches.set(index, timeoutId) 260 }); 261 } 262 263 cancel(index: number): void { 264 const timerId = this.fetches.get(index); 265 if (timerId) { 266 this.fetches.delete(index); 267 clearTimeout(timerId); 268 } 269 } 270 271 totalCount(): number { 272 return this.items.length; 273 } 274 275 getData(index: number): PictureItem { 276 return this.items[index]; 277 } 278 279 registerDataChangeListener(_: DataChangeListener): void { 280 } 281 282 unregisterDataChangeListener(_: DataChangeListener): void { 283 } 284} 285 286function getRandomColor(): number { 287 const maxColorCode = 256; 288 const r = Math.floor(Math.random() * maxColorCode); 289 const g = Math.floor(Math.random() * maxColorCode); 290 const b = Math.floor(Math.random() * maxColorCode); 291 292 return (r * 256 + g) * 256 + b; 293} 294 295function create10x10Bitmap(color: number): ArrayBuffer { 296 const height = 10; 297 const width = 10; 298 299 const fileHeaderLength = 14; 300 const bitmapInfoLength = 40; 301 const headerLength = fileHeaderLength + bitmapInfoLength; 302 const pixelSize = (width * 3 + 2) * height; 303 304 let length = pixelSize + headerLength; 305 306 const buffer = new ArrayBuffer(length); 307 const view16 = new Uint16Array(buffer); 308 309 view16[0] = 0x4D42; 310 view16[1] = length & 0xffff; 311 view16[2] = length >> 16; 312 view16[5] = headerLength; 313 314 let offset = 7; 315 view16[offset++] = bitmapInfoLength & 0xffff; 316 view16[offset++] = bitmapInfoLength >> 16; 317 view16[offset++] = width & 0xffff; 318 view16[offset++] = width >> 16; 319 view16[offset++] = height & 0xffff; 320 view16[offset++] = height >> 16; 321 view16[offset++] = 1; 322 view16[offset++] = 24; 323 324 const b = color & 0xff; 325 const g = (color >> 8) & 0xff; 326 const r = color >> 16; 327 offset = headerLength; 328 const view8 = new Uint8Array(buffer); 329 for (let y = 0; y < height; y++) { 330 for (let x = 0; x < width; x++) { 331 view8[offset++] = b; 332 view8[offset++] = g; 333 view8[offset++] = r; 334 } 335 offset += 2; 336 } 337 338 return buffer; 339} 340``` 341