Flutter 应用中的无限列表

Posted

技术标签:

【中文标题】Flutter 应用中的无限列表【英文标题】:Infinite List in Flutter Application 【发布时间】:2019-04-06 11:30:30 【问题描述】:

我正在将我的应用程序从 android 迁移到颤振,直到现在我已经在颤振中使用了 ListView。我的问题是,是否有任何专门的技术可以处理大量数据?作为参考,您可以查看android RecyclerView。它处理内存中的视图并回收其运行时。那么如何在 Flutter 中实现 RecyclerView 之类的功能呢?还是颤振没有必要?

【问题讨论】:

使用ListView.builder Flutter ListView 类似于 android 中的 ListView。 ListView.builder 类似于 RecyclerView。 Write Your First Flutter App 以ListView.builder 为例,但您可以获取更多关于Working with long lists here 的信息 【参考方案1】:

下面是一个基于chemamolins 答案的简单无限列表小部件。它接受itemBuilder 来构建当前项目,并接受onRequest 回调以在用户滚动到底部时请求更多数据。

import 'package:flutter/material.dart';

typedef Future<List<T>> RequestFn<T>(int nextIndex);
typedef Widget ItemBuilder<T>(BuildContext context, T item, int index);

class InifiniteList<T> extends StatefulWidget 
  final RequestFn<T> onRequest;
  final ItemBuilder<T> itemBuilder;

  const InifiniteList(
      Key? key, required this.onRequest, required this.itemBuilder)
      : super(key: key);

  @override
  _InifiniteListState<T> createState() => _InifiniteListState<T>();


class _InifiniteListState<T> extends State<InifiniteList<T>> 
  List<T> items = [];
  bool end = false;

  _getMoreItems() async 
    final moreItems = await widget.onRequest(items.length);
    if (!mounted) return;

    if (moreItems.isEmpty) 
      setState(() => end = true);
      return;
    
    setState(() => items = [...items, ...moreItems]);
  

  @override
  Widget build(BuildContext context) 
    return ListView.builder(
      itemBuilder: (context, index) 
        if (index < items.length) 
          return widget.itemBuilder(context, items[index], index);
         else if (index == items.length && end) 
          return const Center(child: Text('End of list'));
         else 
          _getMoreItems();
          return const SizedBox(
            height: 80,
            child: Center(child: CircularProgressIndicator()),
          );
        
      ,
      itemCount: items.length + 1,
    );
  

用法

child: InifiniteList<String>(
  onRequest: requestItems,
  itemBuilder: (context, item, index) => Container(
    padding: const EdgeInsets.all(30),
    color: index % 2 == 0 ? Colors.purple.shade100 : Colors.lime.shade100,
    child: Text(item, style: Theme.of(context).textTheme.headline6),
  ),
),
// normally this is the place where you request the next batch of items
// on the network.
Future<List<String>> requestItems(int nextIndex) 
  const pageSize = 15;
  var result = List<String>.generate(pageSize, (i) => "Item: $nextIndex + i + 1");
  return Future<List<String>>.delayed(
    const Duration(milliseconds: 500),
    () => result,
  );

Live Demo

【讨论】:

【参考方案2】:

最简单的方法是使用ListView.builder 而不指定itemCount 参数。

这是最简单的例子:

import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return new MaterialApp(
      home: new MyHomePage(),
    );
  


class MyHomePage extends StatefulWidget 
  @override
  _MyHomePageState createState() => new _MyHomePageState();


class _MyHomePageState extends State<MyHomePage> 
  @override
  Widget build(BuildContext context) 
    return new Scaffold(
      appBar: new AppBar(
        title: new Text("Infinite List"),
      ),
      body: ListView.builder(
        itemBuilder: (context, index) 
          return Text("$index");
        ,
      ),
    );
  

稍后,您可以通过获取真实数据来增强此功能。您可以在等待新数据时在列表的最后一项中显示“CircularProgressIndicator”。

  body: ListView.builder(
    itemBuilder: (context, index) 
      if (index < data.length) 
        // Show your info
        return Text("$index");
       else 
        getMoreData();
        return Center(child: CircularProgressIndicator());
      
    ,
    itemCount: data.length + 1,
  ),

您可以看到我们通过添加索引来欺骗列表,并在显示最终索引时调用更多数据。

getMoreData() 将包括对setState() 的调用以强制重建并考虑新数据。

【讨论】:

我已经为包含真实数据的无限列表添加了一些解释。【参考方案3】:

对于无限滚动 ListView 使用 infinite_scroll_pagination 包,此包管理用户向下滚动屏幕时的延迟加载和显示页面。

添加依赖

dependencies:
  flutter:
    sdk: flutter
  infinite_scroll_pagination: ^2.3.0

在文件顶部向新库添加导入:

import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart';

使用示例

class CharacterListView extends StatefulWidget 
  @override
  _CharacterListViewState createState() => _CharacterListViewState();


class _CharacterListViewState extends State<CharacterListView> 
  static const _pageSize = 20;

  final PagingController<int, CharacterSummary> _pagingController =
      PagingController(firstPageKey: 0);

  @override
  void initState() 
    _pagingController.addPageRequestListener((pageKey) 
      _fetchPage(pageKey);
    );
    super.initState();
  

  Future<void> _fetchPage(int pageKey) async 
    try 
      final newItems = await RemoteApi.getCharacterList(pageKey, _pageSize);
      final isLastPage = newItems.length < _pageSize;
      if (isLastPage) 
        _pagingController.appendLastPage(newItems);
       else 
        final nextPageKey = pageKey + newItems.length;
        _pagingController.appendPage(newItems, nextPageKey);
      
     catch (error) 
      _pagingController.error = error;
    
  

  @override
  Widget build(BuildContext context) => 
      // Don't worry about displaying progress or error indicators on screen; the 
      // package takes care of that. If you want to customize them, use the 
      // [PagedChildBuilderDelegate] properties.
      PagedListView<int, CharacterSummary>(
        pagingController: _pagingController,
        builderDelegate: PagedChildBuilderDelegate<CharacterSummary>(
          itemBuilder: (context, item, index) => CharacterListItem(
            character: item,
          ),
        ),
      );

  @override
  void dispose() 
    _pagingController.dispose();
    super.dispose();
  

【讨论】:

【参考方案4】:

显示数据列表是移动应用的基本模式。 Flutter 包含 ListView 小部件,使处理列表变得轻而易举。

我已经通过以下步骤解决了这个问题

    使用 ListView 小部件 ListView类有四个构造函数 您必须使用 Builder 构造函数 (ListView.builder) 当您必须按需制作元素列表时,使用 Builder 构造函数 适用于具有大量(或无限)子级的列表视图

在这里您可以观看解决方案视频CLICK HERE

【讨论】:

以上是关于Flutter 应用中的无限列表的主要内容,如果未能解决你的问题,请参考以下文章

Flutter 在无限循环中发送 http 请求

如何使用 Flutter 从 Firestore 中的 ListView 获得无限滚动

在 Flutter 中使用 Cloud Firestore 创建无限列表

Flutter 中的底部被无限像素溢出

android studio/flutter 无限说“正在初始化 gradle”

无法从 Flutter 中的 Firebase Firestore 返回列表