写点什么

Flutter & 鸿蒙 Next 中封装一个列表组件

作者:淼.
  • 2025-03-14
    北京
  • 本文字数:2784 字

    阅读完需:约 9 分钟

在移动应用开发中,列表组件是使用频率最高的组件之一。无论是展示新闻、商品、聊天记录还是其他数据,列表组件都扮演着重要角色。为了提升开发效率和代码复用性,封装一个通用的列表组件是十分必要的。本文将详细介绍如何在 Flutter 和鸿蒙 Next 中封装一个功能强大且灵活的列表组件。



一、Flutter 中封装列表组件

(一)基础列表组件

在 Flutter 中,ListView 是实现列表的常用组件。它支持滚动显示多个子组件,并且可以轻松实现动态加载和分页。

(二)封装通用列表组件

为了封装一个通用的列表组件,我们需要考虑以下功能:


  1. 数据加载:支持动态加载数据。

  2. 分页加载:支持滚动到底部时自动加载更多数据。

  3. 空状态显示:当数据为空时显示友好的提示。

  4. 错误处理:显示加载失败的提示,并允许用户重试。

  5. 自定义样式:允许开发者自定义列表项的样式。


以下是一个封装好的通用列表组件的实现:


import 'package:flutter/material.dart';
class GenericList<T> extends StatefulWidget { final Future<List<T>> Function(int page) loadData; final Widget Function(T item) itemBuilder; final int initialPage; final int pageSize;
const GenericList({ Key? key, required this.loadData, required this.itemBuilder, this.initialPage = 1, this.pageSize = 10, }) : super(key: key);
@override _GenericListState<T> createState() => _GenericListState<T>();}
class _GenericListState<T> extends State<GenericList<T>> { List<T> _items = []; int _currentPage = 1; bool _isLoading = false; bool _hasMore = true;
@override void initState() { super.initState(); _loadData(); }
Future<void> _loadData() async { if (_isLoading || !_hasMore) return; setState(() => _isLoading = true); try { final List<T> newData = await widget.loadData(_currentPage); setState(() { _items.addAll(newData); _currentPage++; _hasMore = newData.length == widget.pageSize; }); } catch (e) { print('Error loading data: $e'); } finally { setState(() => _isLoading = false); } }
@override Widget build(BuildContext context) { return NotificationListener<ScrollNotification>( onNotification: (ScrollNotification scrollInfo) { if (!_isLoading && scrollInfo.metrics.pixels == scrollInfo.metrics.maxScrollExtent) { _loadData(); } return true; }, child: ListView.builder( itemCount: _items.length + (_hasMore ? 1 : 0), itemBuilder: (context, index) { if (index < _items.length) { return widget.itemBuilder(_items[index]); } else { return Center(child: CircularProgressIndicator()); } }, ), ); }}
复制代码

(三)使用封装的列表组件

以下是一个使用封装的列表组件的示例:


class MyHomePage extends StatelessWidget {  @override  Widget build(BuildContext context) {    return Scaffold(      appBar: AppBar(title: Text('通用列表组件示例')),      body: GenericList<String>(        loadData: (page) async {          await Future.delayed(Duration(seconds: 2)); // 模拟网络延迟          return List.generate(10, (index) => 'Item ${page * 10 + index}');        },        itemBuilder: (item) => ListTile(title: Text(item)),      ),    );  }}
复制代码



二、鸿蒙 Next 中封装列表组件

鸿蒙 Next 提供了强大的组件化开发能力,可以实现类似的列表封装。虽然 API 和 Flutter 有所不同,但核心思想是类似的。

(一)基础列表组件

在鸿蒙 Next 中,List 组件用于实现列表。它支持滚动显示多个子组件,并且可以轻松实现动态加载和分页。

(二)封装通用列表组件

以下是一个封装好的通用列表组件的实现:


import { Component, State, OnAppear, OnDisappear } from '@ohos.arkui';import { List, ListItem, Text, Button } from '@ohos.arkui';
@Componentstruct GenericList<T> { @State items: T[] = []; @State currentPage: number = 1; @State isLoading: boolean = false; @State hasMore: boolean = true;
private loadData: (page: number) => Promise<T[]>;
constructor(loadData: (page: number) => Promise<T[]>) { this.loadData = loadData; }
@OnAppear onAppear() { this._loadData(); }
private async _loadData() { if (this.isLoading || !this.hasMore) return; this.isLoading = true; try { const newData = await this.loadData(this.currentPage); this.items = [...this.items, ...newData]; this.currentPage++; this.hasMore = newData.length > 0; } catch (e) { console.error('Error loading data:', e); } finally { this.isLoading = false; } }
build() { return ( <List onScrollEnd={() => { if (!this.isLoading && this.hasMore) { this._loadData(); } }} > {this.items.map((item, index) => ( <ListItem key={index}> <Text>{String(item)}</Text> </ListItem> ))} {this.hasMore && ( <ListItem> <Text>加载中...</Text> </ListItem> )} </List> ); }}
复制代码

(三)使用封装的列表组件

以下是一个使用封装的列表组件的示例:


@Componentstruct MyHomePage {  build() {    return (      <GenericList<string>        loadData={(page) => {          return new Promise((resolve) => {            setTimeout(() => {              resolve(Array.from({ length: 10 }, (_, i) => `Item ${page * 10 + i}`));            }, 2000);          });        }}      />    );  }}
复制代码



三、总结

通过封装通用的列表组件,我们可以显著提升开发效率和代码复用性。在 Flutter 中,ListView 是实现列表的核心组件,通过结合 NotificationListener 和分页加载逻辑,可以实现动态加载和分页功能。在鸿蒙 Next 中,List 组件提供了类似的功能,通过监听滚动事件实现分页加载。


希望本文能帮助你更好地理解和实现通用列表组件。如果你有任何问题或需要进一步的帮助,欢迎随时交流!

用户头像

淼.

关注

还未添加个人签名 2022-10-24 加入

还未添加个人简介

评论

发布
暂无评论
Flutter & 鸿蒙 Next 中封装一个列表组件_淼._InfoQ写作社区