Flutter&OpenHarmony下拉刷新与加载更多

前言

下拉刷新和加载更多是移动应用中处理列表数据的标准交互模式。下拉刷新允许用户手动触发数据更新,获取最新内容;加载更多则在用户滚动到列表底部时自动加载下一页数据。在笔记应用中,这两个功能对于展示大量笔记列表、同步云端数据等场景非常重要。本文将详细介绍如何在Flutter和OpenHarmony平台上实现下拉刷新和加载更多功能。

Flutter下拉刷新实现

Flutter提供了RefreshIndicator组件实现下拉刷新功能。

dart 复制代码
class NotesListPage extends StatefulWidget {
  @override
  _NotesListPageState createState() => _NotesListPageState();
}

class _NotesListPageState extends State<NotesListPage> {
  List<Note> _notes = [];
  bool _isLoading = false;
  
  Future<void> _refreshNotes() async {
    setState(() => _isLoading = true);
    try {
      final notes = await NoteService.fetchNotes();
      setState(() {
        _notes = notes;
      });
    } finally {
      setState(() => _isLoading = false);
    }
  }
}

下拉刷新需要维护加载状态和数据列表。_isLoading用于显示加载指示器,_notes存储笔记数据。_refreshNotes方法是异步的,它先设置加载状态为true,然后调用服务获取数据,最后更新列表并重置加载状态。try-finally确保无论成功还是失败都会重置加载状态。这种状态管理模式是处理异步数据加载的标准做法。

dart 复制代码
@override
Widget build(BuildContext context) {
  return RefreshIndicator(
    onRefresh: _refreshNotes,
    color: Colors.blue,
    backgroundColor: Colors.white,
    child: ListView.builder(
      itemCount: _notes.length,
      itemBuilder: (context, index) {
        return NoteListItem(note: _notes[index]);
      },
    ),
  );
}

RefreshIndicator包裹可滚动的子组件,当用户下拉时显示刷新指示器。onRefresh回调必须返回Future,当Future完成时刷新指示器自动隐藏。color设置指示器的颜色,backgroundColor设置指示器背景色。ListView.builder作为子组件展示笔记列表。这种组合使用方式简洁高效,开发者只需关注数据加载逻辑,刷新动画由框架自动处理。

加载更多实现

加载更多需要监听列表滚动位置。

dart 复制代码
class _NotesListPageState extends State<NotesListPage> {
  final ScrollController _scrollController = ScrollController();
  List<Note> _notes = [];
  bool _isLoadingMore = false;
  bool _hasMore = true;
  int _page = 1;
  
  @override
  void initState() {
    super.initState();
    _scrollController.addListener(_onScroll);
    _loadNotes();
  }
  
  void _onScroll() {
    if (_scrollController.position.pixels >= 
        _scrollController.position.maxScrollExtent - 200) {
      _loadMoreNotes();
    }
  }
}

ScrollController用于监听列表的滚动事件。在initState中添加滚动监听器,_onScroll方法检查当前滚动位置是否接近底部。当距离底部小于200像素时触发加载更多。_page记录当前页码,_hasMore标记是否还有更多数据。这种提前触发的设计可以让用户在滚动过程中无缝加载新数据,提升体验流畅度。

dart 复制代码
Future<void> _loadMoreNotes() async {
  if (_isLoadingMore || !_hasMore) return;
  
  setState(() => _isLoadingMore = true);
  try {
    final newNotes = await NoteService.fetchNotes(page: _page + 1);
    setState(() {
      _notes.addAll(newNotes);
      _page++;
      _hasMore = newNotes.isNotEmpty;
    });
  } finally {
    setState(() => _isLoadingMore = false);
  }
}

_loadMoreNotes方法首先检查是否正在加载或已无更多数据,避免重复请求。加载成功后将新数据追加到列表末尾,页码加1,并根据返回数据是否为空判断是否还有更多数据。这种分页加载的模式可以有效减少单次请求的数据量,提升加载速度和用户体验。

dart 复制代码
Widget build(BuildContext context) {
  return RefreshIndicator(
    onRefresh: _refreshNotes,
    child: ListView.builder(
      controller: _scrollController,
      itemCount: _notes.length + (_hasMore ? 1 : 0),
      itemBuilder: (context, index) {
        if (index == _notes.length) {
          return _buildLoadingIndicator();
        }
        return NoteListItem(note: _notes[index]);
      },
    ),
  );
}

Widget _buildLoadingIndicator() {
  return Container(
    padding: EdgeInsets.all(16),
    alignment: Alignment.center,
    child: CircularProgressIndicator(),
  );
}

列表的itemCount在有更多数据时加1,用于显示加载指示器。itemBuilder中判断如果是最后一项则显示加载指示器,否则显示笔记项。这种设计将加载指示器作为列表的一部分,当用户滚动到底部时自然看到加载状态。CircularProgressIndicator是Material风格的圆形进度指示器,居中显示在列表底部。

OpenHarmony下拉刷新

OpenHarmony使用Refresh组件实现下拉刷新。

typescript 复制代码
@Entry
@Component
struct NotesListPage {
  @State noteList: NoteItem[] = []
  @State isRefreshing: boolean = false
  
  async loadNotes() {
    this.isRefreshing = true
    try {
      let notes = await NoteService.fetchNotes()
      this.noteList = notes
    } finally {
      this.isRefreshing = false
    }
  }
  
  build() {
    Refresh({ refreshing: this.isRefreshing }) {
      List() {
        ForEach(this.noteList, (item: NoteItem) => {
          ListItem() {
            this.NoteItemBuilder(item)
          }
        })
      }
    }
    .onRefreshing(() => {
      this.loadNotes()
    })
  }
}

OpenHarmony的Refresh组件包裹List实现下拉刷新功能。refreshing属性绑定刷新状态,当为true时显示刷新指示器。onRefreshing回调在用户下拉触发刷新时调用,开发者需要在数据加载完成后手动将isRefreshing设置为false。这种显式的状态管理方式让开发者对刷新流程有完全的控制权。

typescript 复制代码
Refresh({ refreshing: this.isRefreshing, offset: 100, friction: 100 }) {
  List() {
    ForEach(this.noteList, (item: NoteItem) => {
      ListItem() {
        this.NoteItemBuilder(item)
      }
    })
  }
}
.onRefreshing(() => {
  this.loadNotes()
})
.onStateChange((state: RefreshStatus) => {
  if (state === RefreshStatus.Done) {
    console.log('刷新完成')
  }
})

Refresh组件提供了更多配置选项。offset设置触发刷新的下拉距离阈值,friction设置下拉的阻尼系数。onStateChange回调可以监听刷新状态的变化,RefreshStatus包含Inactive、Drag、OverDrag、Refresh、Done等状态。通过这些配置和回调,开发者可以精细控制下拉刷新的行为和反馈。

OpenHarmony加载更多

typescript 复制代码
@Entry
@Component
struct NotesListPage {
  @State noteList: NoteItem[] = []
  @State isLoadingMore: boolean = false
  @State hasMore: boolean = true
  private page: number = 1
  
  build() {
    List() {
      ForEach(this.noteList, (item: NoteItem) => {
        ListItem() {
          this.NoteItemBuilder(item)
        }
      })
      
      if (this.hasMore) {
        ListItem() {
          this.LoadingIndicatorBuilder()
        }
      }
    }
    .onReachEnd(() => {
      this.loadMoreNotes()
    })
  }
}

OpenHarmony的List组件提供了onReachEnd回调,当列表滚动到底部时自动触发。这比手动监听滚动位置更加简洁。列表末尾根据hasMore状态显示加载指示器。这种声明式的写法使得加载更多的实现非常直观,开发者只需关注数据加载逻辑。

typescript 复制代码
async loadMoreNotes() {
  if (this.isLoadingMore || !this.hasMore) return
  
  this.isLoadingMore = true
  try {
    let newNotes = await NoteService.fetchNotes(this.page + 1)
    this.noteList = this.noteList.concat(newNotes)
    this.page++
    this.hasMore = newNotes.length > 0
  } finally {
    this.isLoadingMore = false
  }
}

@Builder
LoadingIndicatorBuilder() {
  Row() {
    LoadingProgress()
      .width(24)
      .height(24)
    Text('加载中...')
      .fontSize(14)
      .fontColor('#999999')
      .margin({ left: 8 })
  }
  .width('100%')
  .height(50)
  .justifyContent(FlexAlign.Center)
}

loadMoreNotes方法的逻辑与Flutter版本类似,先检查状态避免重复加载,然后请求数据并追加到列表。LoadingIndicatorBuilder使用@Builder装饰器定义加载指示器的UI,LoadingProgress是OpenHarmony提供的加载动画组件。Row水平排列加载动画和提示文字,居中显示在列表底部。

空状态处理

当列表为空时需要显示空状态提示。

dart 复制代码
Widget build(BuildContext context) {
  if (_notes.isEmpty && !_isLoading) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Icon(Icons.note, size: 64, color: Colors.grey),
          SizedBox(height: 16),
          Text('暂无笔记', style: TextStyle(color: Colors.grey)),
          SizedBox(height: 8),
          ElevatedButton(
            onPressed: _refreshNotes,
            child: Text('刷新'),
          ),
        ],
      ),
    );
  }
  return RefreshIndicator(/* ... */);
}

空状态页面显示图标、提示文字和刷新按钮,引导用户进行下一步操作。判断条件需要同时检查列表为空且不在加载中,避免在首次加载时显示空状态。这种友好的空状态设计可以提升用户体验,让用户知道当前状态并提供操作入口。

总结

下拉刷新和加载更多是列表数据展示的标准功能。Flutter和OpenHarmony都提供了便捷的实现方式,开发者需要合理管理加载状态、处理分页逻辑、提供加载反馈。通过这些功能的实现,笔记应用可以高效地展示大量数据,同时保持良好的用户体验。

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

相关推荐
程序员Ctrl喵9 小时前
异步编程:Event Loop 与 Isolate 的深层博弈
开发语言·flutter
前端不太难11 小时前
Flutter 如何设计可长期维护的模块边界?
flutter
小蜜蜂嗡嗡12 小时前
flutter列表中实现置顶动画
flutter
始持12 小时前
第十二讲 风格与主题统一
前端·flutter
始持12 小时前
第十一讲 界面导航与路由管理
flutter·vibecoding
始持12 小时前
第十三讲 异步操作与异步构建
前端·flutter
新镜13 小时前
【Flutter】 视频视频源横向、竖向问题
flutter
黄林晴13 小时前
Compose Multiplatform 1.10 发布:统一 Preview、Navigation 3、Hot Reload 三箭齐发
android·flutter
Swift社区14 小时前
Flutter 应该按功能拆,还是按技术层拆?
flutter
肠胃炎14 小时前
树形选择器组件封装
前端·flutter