当前位置: 首页 > 编程笔记 >

Flutter ListView 分页加载更多效果

路奇
2023-03-14
本文向大家介绍Flutter ListView 分页加载更多效果,包括了Flutter ListView 分页加载更多效果的使用技巧和注意事项,需要的朋友参考一下

对于REST API接口,大部分情况下都得处理分页问题。

分页可以让我们把大量数据分割成一个个小段,分次加载。这样可以有效避免因为一次load全部数据而导致客户端变慢的问题。

本文介绍Flutter ListView组件的分页实现,数据来源于HTTP请求。当用户下拉时,APP自动加载更多数据。

1 创建 Stateful Widgets

首先,要为 ListView 绑定为 Stateful 组件,以便能加载新数据。

ListView的状态(state)信息可以在组件创建时异步加载,也能在组件的生命周期里面用setState修改。

import 'package:flutter/material.dart';
 import 'package:dio/dio.dart';
 void main() => runApp(MyApp());
 class MyApp extends StatelessWidget {
   @override
   Widget build(BuildContext context) {
     return MaterialApp(
       title: 'Flutter Demo',
       theme: ThemeData(
         primarySwatch: Colors.blue,
       ),
       home: MyHomePage(),
     );
   }
 }
 class MyHomePage extends StatefulWidget {
   @override
   _MyHomePageState createState() => _MyHomePageState();
 }
 class _MyHomePageState extends State<MyHomePage> {
 String nextPage = "https://swapi.co/api/people";
 ScrollController _scrollController = new ScrollController();
 bool isLoading = false;
 List names = new List();  
 ….
 @override
   Widget build(BuildContext context) {
     return Scaffold(
       appBar: AppBar(
         title: const Text("Pagination"),
       ),
       body: Container(
         child: _buildList(),
       ),
       resizeToAvoidBottomPadding: false,
     );
   }
 }

这里,当我们下拉但是还未收到数据时,resizeToAvoidBottomPadding 可以保留出一个空位,loading效果就能显示在这个空位中。

2 使用dio拉取HTTP接口数据

为模拟实际场景,我们这里从API接口拉取数据,以让我们更好地理解Flutter的分页机制。

这里我们用公开的SWAPI接口,这个接口支持分页返回人名。

2.1 添加依赖

dependencies:
  # ....
  dio: 2.0.22 # check for latest version.

dio是Dart的Http客户端,支持拦截器、全局配置、表单数据、请求撤销、文件下载和超时等。

2.2 请求数据方法

因为 SWAPI接口返回数据包含下一页URL,所以数据请求方法我们这样写:

ffinal dio = new Dio();

void _getMoreData() async {
  if (!isLoading) {
    setState(() {
      isLoading = true;
    });

    final response = await dio.get(nextPage);
    nextPage = response.data['next'];

    setState(() {
      isLoading = false;
      names.addAll(response.data['results']);
    });
  }
}

在 _getMoreData 方法中,我们通过网络请求来获取列表的更多数据。

3 加载更多数据

接着我们来看看 scrollController 组件。scrollController 是一个滑动监听组件,这里我们用来控制何时加载数据。

当我们滑动界面时,如果没有达到尾页,并且数据不是正在加载中状态,scrollController 就会检查当前视图所在的位置来决定是否加载更多数据。

@override
   void initState() {
     this._getMoreData();
     super.initState();
     _scrollController.addListener(() {
       if (_scrollController.position.pixels ==
           _scrollController.position.maxScrollExtent) {
         _getMoreData();
       }
     });
   }
 @override
   void dispose() {
     _scrollController.dispose();
     super.dispose();
   }

ListView 支持 scrollController 事件绑定,当用户在ListView中滑动时,会出发 scrollController 事件。

现在,当我们滑动到单个 ListView 底部时,_getMoreData() 会获取新数据,并保存到组件的state中。

4 显示ListView加载状态

在ListView builder中,我们使用一个技巧来让最后一行显示加载条(ProgressBar)。

Widget _buildProgressIndicator() {
     return new Padding(
       padding: const EdgeInsets.all(8.0),
       child: new Center(
         child: new Opacity(
           opacity: isLoading ? 1.0 : 0.0,
           child: new CircularProgressIndicator(),
         ),
       ),
     );
   }

 Widget _buildList() {
     return ListView.builder(
       //+1 for progressbar
       itemCount: names.length + 1,
       itemBuilder: (BuildContext context, int index) {
         if (index == names.length) {
           return _buildProgressIndicator();
         } else {
           return new ListTile(
             title: Text((names[index]['name'])),
             onTap: () {
               print(names[index]);
             },
           );
         }
       },
       controller: _scrollController,
     );
   }

5 完整代码

import 'package:flutter/material.dart';
import 'package:dio/dio.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

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

class _MyHomePageState extends State<MyHomePage> {

  String nextPage = "https://swapi.co/api/people";

  ScrollController _scrollController = new ScrollController();

  bool isLoading = false;

  List names = new List();


  final dio = new Dio();

  void _getMoreData() async {
    if (!isLoading) {
      setState(() {
        isLoading = true;
      });

      final response = await dio.get(nextPage);

      nextPage = response.data['next'];

      setState(() {
        isLoading = false;
        names.addAll(response.data['results']);
      });
    }
  }

  @override
  void initState() {
    this._getMoreData();
    super.initState();
    _scrollController.addListener(() {
      if (_scrollController.position.pixels ==
          _scrollController.position.maxScrollExtent) {
        _getMoreData();
      }
    });
  }

  @override
  void dispose() {
    _scrollController.dispose();
    super.dispose();
  }

  Widget _buildProgressIndicator() {
    return new Padding(
      padding: const EdgeInsets.all(8.0),
      child: new Center(
        child: new Opacity(
          opacity: isLoading ? 1.0 : 00,
          child: new CircularProgressIndicator(),
        ),
      ),
    );
  }

  Widget _buildList() {
    return ListView.builder(
//+1 for progressbar
      itemCount: names.length + 1,
      itemBuilder: (BuildContext context, int index) {
        if (index == names.length) {
          return _buildProgressIndicator();
        } else {
          return new ListTile(
            title: Text((names[index]['name'])),
            onTap: () {
              print(names[index]);
            },
          );
        }
      },
      controller: _scrollController,
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("Pagination"),
      ),
      body: Container(
        child: _buildList(),
      ),
      resizeToAvoidBottomPadding: false,
    );
  }
}

英文原文:Flutter ListView REST API Pagination

 类似资料:
  • Loadmore用于实现加载更多的效果,使用比较简单,加上相关的 class 就可以实现这种效果,示例代码如下: <template> <div class="page"> <div class="weui-loadmore"> <div class="weui-loading"></div> <div class="weui-loadmore__tips">正

  • loadMore 加载更多 平台差异说明 App H5 微信小程序 支付宝小程序 百度小程序 头条小程序 QQ小程序 √ √ √ √ √ √ √ 基本使用 通过status设置组件的状态,加载前值为loadmore,加载中为loading,没有数据为nomore 注意:以下示例仅为模拟效果,实际中请根据自己的逻辑,修改代码的实现 <template> <view class="wrap">

  • 好的,首先,我将告诉这应该如何工作:我有一个页面的图片链接下侧,点击一个图片,该链接的信息出现在另一个div。我使用jQuery/Ajax将链接id发布到一个php文件中,并将该数据返回到所选的div。链接应该分页,以便一次显示4个。 这是正在发生的事情:post部分是ok的,当我单击一个链接时,正确的数据将显示在所选的div中。我不知道如何使链接div分页虽然。我需要他们分页时,页面加载,现在当

  • 本文向大家介绍Android ExpandableListView实现下拉刷新和加载更多效果,包括了Android ExpandableListView实现下拉刷新和加载更多效果的使用技巧和注意事项,需要的朋友参考一下 支持下拉刷新和加载更多的ExpandableListView,供大家参考,具体内容如下 模拟器有点卡,滑动的时候鼠标不方便 怎么用: XML中声明 UI中配置下拉刷新的回调以及是否

  • 本文向大家介绍jQuery给表格添加分页效果,包括了jQuery给表格添加分页效果的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了jQuery表格添加分页的具体代码,供大家参考,具体内容如下 1. 新建一个Table,添加十行数据 2. 引入jQuery 及script代码 3. 另外,附上表格和底部分页码的css样式 4.好了,打开浏览器试试 点击页码可翻页,成功! 更多精彩内容请