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