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