如何解决Refresh每次下拉重复触发刷新回调的问题
==========================

#### 问题现象

Refresh组件在反复滑动时，会重复触发刷新回调，无法控制刷新状态，问题图如下：

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/73/v3/ZO4IywDySHKkBqI7zIEROw/zh-cn_image_0000002658914537.png?HW-CC-KV=V1&HW-CC-Date=20260709T133913Z&HW-CC-Expire=86400&HW-CC-Sign=799D0A4C150517C5A6A7D093586D407A02951188F7C41FD591A9B9AF3CB900CE "点击放大")

由图可见，Refresh的刷新不断重复触发，如何解决Refresh每次下拉重复触发刷新回调的问题？

#### 背景知识

[Refresh](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-container-refresh)是可以进行页面下拉操作并显示刷新动效的容器组件，其[onRefreshing](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-container-refresh#onrefreshing)回调会在进入刷新状态时触发。

#### 解决方案

通过给onRefreshing刷新回调增加限制条件来限制其触发频率，具体实现如下：

1.  使用@State装饰器定义多个状态变量，如arr、refreshing、refreshOffset等。
    
    @State arr: Array<number> = \[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10\];
    @State refreshing: boolean = false;
    @State refreshOffset: number = 0;
    @State refreshState: RefreshStatus = RefreshStatus.Inactive;
    @State canLoad: boolean = false;
    @State isLoading: boolean = false;
    @State isRefresh: boolean = true;
    
2.  在onScrollFrameBegin回调中，监听用户下拉操作，当下拉距离超过阈值且没有正在加载时，设置canLoad为true，允许加载更多数据。
    
    .onScrollFrameBegin((offset: number) => {
      if (offset > 5 && !this.isLoading) {
        this.canLoad = true;
      }
      return { offsetRemain: offset };
    })
    
3.  在onRefreshing回调中，处理刷新状态的逻辑，当触发刷新时，设置refreshing为true，并在6秒后恢复为false。
    
    .onRefreshing(() => {
      if (this.refreshing) {
        this.isRefresh = false;
      }
      console.info(\`SystemRefreshPage\`, \`refreshing:${this.refreshing}\`);
      setTimeout(() => {
        this.refreshing = false;
        this.isRefresh = true;
      }, 6000);
    });
    

完整代码示例如下：

@Entry
@Component
struct RefreshRepeatProblem {
  @State arr: Array<number> = \[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10\];
  @State refreshing: boolean = false;
  @State refreshOffset: number = 0;
  @State refreshState: RefreshStatus = RefreshStatus.Inactive;
  @State canLoad: boolean = false;
  @State isLoading: boolean = false;
  @State isRefresh: boolean = true;


  build() {
    Refresh({ refreshing: $$this.refreshing }) {
      List() {
        ForEach(this.arr, (item: number) => {
          ListItem() {
            Text('' + item)
              .width('100%')
              .height(80)
              .fontSize(16)
              .textAlign(TextAlign.Center)
              .backgroundColor('#F1F3F5')
              .borderRadius(15);
          }.expandSafeArea(\[SafeAreaType.SYSTEM\], \[SafeAreaEdge.BOTTOM\]).margin({ top: 7, bottom: 7, left: 20 });
        }, (item: string) => item);
      }.expandSafeArea(\[SafeAreaType.SYSTEM\], \[SafeAreaEdge.BOTTOM\])
      .width('92%')
      .margin({right:20})
      .onScrollIndex((end: number) => {
        if (this.canLoad && end >= this.arr.length - 1) {
          this.canLoad = false;
          this.isLoading = true;
          setTimeout(() => {
            for (let i = 0; i < 10; i++) {
              this.arr.push(this.arr.length);
              this.isLoading = false;
            }
          }, 6000);
        }
      })
      .onScrollFrameBegin((offset: number) => {
        if (offset > 5 && !this.isLoading) {
          this.canLoad = true;
        }
        return { offsetRemain: offset };
      })
      .scrollBar(BarState.Off)
      .edgeEffect(EdgeEffect.Spring, { alwaysEnabled: true });
    }.expandSafeArea(\[SafeAreaType.SYSTEM\], \[SafeAreaEdge.BOTTOM\])
    .width('100%')
    .height('100%')
    .backgroundColor('#ffffffff')
    .pullToRefresh(this.isRefresh)
    .onOffsetChange((offset: number) => {
      this.refreshOffset = offset;
    })
    .onStateChange((state: RefreshStatus) => {
      this.refreshState = state;
    })
    .onRefreshing(() => {
      if (this.refreshing) {
        this.isRefresh = false;
      }
      console.info(\`SystemRefreshPage\`, \`refreshing:${this.refreshing}\`);
      setTimeout(() => {
        this.refreshing = false;
        this.isRefresh = true;
      }, 6000);
    });
  }
}

修正效果图如下：

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/12/v3/WDAAYU2HQJyl04-XJTp9Bg/zh-cn_image_0000002628395312.png?HW-CC-KV=V1&HW-CC-Date=20260709T133913Z&HW-CC-Expire=86400&HW-CC-Sign=B1C7ADB732B97D725FD36CF85DF3DE50D46419999F57436E32F087A4ACCD210E "点击放大")

由图可见，Refresh组件的刷新状态不会在短时间内频繁触发。