• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16interface IPrefetchRangeEvaluator {
17  get rangeToPrefetch(): IndexRange;
18  setTotal(totalItems: number): void;
19  visibleRangeChanged(minVisible: number, maxVisible: number): void;
20  itemPrefetched(index: number, fetchDuration: number): void;
21}
22
23class PrefetchRangeEvaluator implements IPrefetchRangeEvaluator {
24  private readonly itemsOnScreen = new ItemsOnScreenProvider();
25  private readonly prefetchCount = new PrefetchCount(this.itemsOnScreen);
26  private readonly fetchedRegistry = new FetchedRegistry();
27  private readonly prefetchRangeRatio = new PrefetchRangeRatio(this.itemsOnScreen, this.fetchedRegistry);
28  private totalItems = 0;
29  private rangeToPrefetch_ = new IndexRange(0, 0);
30
31  get rangeToPrefetch(): IndexRange {
32    return this.rangeToPrefetch_;
33  }
34
35  setTotal(totalItems: number): void {
36    this.totalItems = totalItems;
37  }
38
39  visibleRangeChanged(minVisible: number, maxVisible: number): void {
40    this.itemsOnScreen.update(minVisible, maxVisible);
41
42    Logger.log(
43      `visibleAreaChanged itemsOnScreen=${
44        Math.abs(maxVisible - minVisible) + 1
45      }, meanImagesOnScreen=${this.itemsOnScreen.meanValue}, prefetchCountCurrentLimit=${this.prefetchCount.currentLimit}, prefetchCountMaxRatio=${this.prefetchCount.maxRatio}`,
46    );
47
48    // +1 for inclusive maxVisible -> exclusive end
49    this.prefetchCount.prefetchCountValue = this.evaluatePrefetchCount('visible-area-changed');
50    this.rangeToPrefetch_ = this.prefetchCount.getRangeToPrefetch(this.totalItems);
51    this.fetchedRegistry.updateRangeToPrefetch(this.rangeToPrefetch_);
52  }
53
54  itemPrefetched(index: number, fetchDuration: number): void {
55    let maxRatioChanged = false;
56    if (this.prefetchRangeRatio.update(fetchDuration) === 'ratio-changed') {
57      this.prefetchCount.maxRatio = this.prefetchRangeRatio.maxRatio;
58      maxRatioChanged = true;
59      Logger.log(
60        `choosePrefetchCountLimit prefetchCountMaxRatio=${this.prefetchCount.maxRatio}, prefetchCountCurrentLimit=${this.prefetchCount.currentLimit}`,
61      );
62    }
63
64    this.fetchedRegistry.addFetched(index);
65
66    this.prefetchCount.prefetchCountValue = this.evaluatePrefetchCount('resolved', maxRatioChanged);
67    this.rangeToPrefetch_ = this.prefetchCount.getRangeToPrefetch(this.totalItems);
68    this.fetchedRegistry.updateRangeToPrefetch(this.rangeToPrefetch_);
69  }
70
71  private evaluatePrefetchCount(event: 'resolved' | 'visible-area-changed', maxRatioChanged?: boolean): number {
72    const ratio = this.prefetchRangeRatio.calculateRatio(this.prefetchCount.prefetchCountValue, this.totalItems);
73    let evaluatedPrefetchCount = this.prefetchCount.getPrefetchCountByRatio(ratio);
74
75    let nextRatio: number | undefined;
76
77    if (maxRatioChanged) {
78      nextRatio = this.prefetchRangeRatio.calculateRatio(evaluatedPrefetchCount, this.totalItems);
79      evaluatedPrefetchCount = this.prefetchCount.getPrefetchCountByRatio(nextRatio);
80    }
81
82    if (
83      this.prefetchRangeRatio.range.contains(ratio) ||
84      (event === 'resolved' && evaluatedPrefetchCount <= this.prefetchCount.prefetchCountValue)
85    ) {
86      return this.prefetchCount.prefetchCountValue;
87    }
88
89    this.prefetchRangeRatio.updateRatioRange(ratio);
90    Logger.log(
91      `evaluatePrefetchCount prefetchCount=${evaluatedPrefetchCount}, ratio=${ratio}, nextRatio=${nextRatio}, hysteresisRange=${this.prefetchRangeRatio.range}`,
92    );
93    return evaluatedPrefetchCount;
94  }
95}
96