Flutter项目实战-我的第一个Flutter项目-列表页的刷新和加载(六)

298 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 4 天,点击查看活动详情

一、前言

上一篇文章我们简单实现了一个固定长度的列表,这一篇我们给这个列表加点儿上拉加载和下拉刷新的数据变换.

二、控件状态

当Flutter页面需要动态更新数据时,此时涉及到了UI组件根据数据发生变化,Flutter页面也有了多种状态。之前的Flutter控件提到了无状态组件(StatelessWidget)和有状态组件(StatefulWidget).

很明显,此时我们必须使用StatefulWidget组件了,通过调用setState方法通知界面刷新.有状态组件还可以通过initialState初始化状态.

三、异步 async/await

Android网络编程中对于异步请求,我们可以开启子线程执行耗时任务,主线程和子线程还可以通过handler实现消息通信.Flutter中可以使用async和await.

标记为async的函数返回结果是一个Future包裹的对象,调用方可以使用await从中获取实际返回的数据.在结果没有返回的时候,主线程会执行其他任务.

此时的数据获取还是上节的方式.增加了async方式用来模拟网络请求.

class DynamicMockData {
  static Future<List<Map<String, Object>>> list(int page, int size) async {
    return List<Map<String, Object>>.generate(size, (index) {
      return {
        'title': '标题${index + (page - 1) * size + 1}:这是一个列表标题,最多两行,多处部分会被截取',
        'imageUrl':
            'https://t7.baidu.com/it/u=963301259,1982396977&fm=193&f=GIF',
        'viewCount': 20,
      };
    });
  }
}

调用时,使用await获取结果数据.

List<Map<String, Object>> _listItems = await DynamicMockData.list(1, PAGE_SIZE);

四、flutter刷新库

在pubspec.yaml文件中指定刷新库和相应版本号即可,后续执行一下pub get更新一下依赖.

dependencies:
  flutter:
    sdk: flutter


  # The following adds the Cupertino Icons font to your application.
  # Use with the CupertinoIcons class for iOS style icons.
  cupertino_icons: ^1.0.2
  flutter_easyrefresh: ^2.2.2

五、EasyRefresh

当我们使用EasyRefresh包裹列表组件时,指定onRefresh和onLoad的回调方法,在相应方法里进行数据的获取.

import 'package:fftest1/dynamic_item.dart';
import 'package:flutter/material.dart';
import 'package:flutter_easyrefresh/easy_refresh.dart';

class TabDynamicPage extends StatefulWidget {
  TabDynamicPage({Key? key}) : super(key: key);

  @override
  State<StatefulWidget> createState() => _TabDynamicPageState();
}

class _TabDynamicPageState extends State<TabDynamicPage> {
  static const int PAGE_SIZE = 20;
  int _currentPage = 1;

  List<Map<String, Object>> _listItems = [];

  void _refresh() async {
    _currentPage = 1;
    _requestNewItems();
  }

  void _load() async {
    _currentPage += 1;
    _requestNewItems();
  }

  void _requestNewItems() async {
    List<Map<String, Object>> _newItems =
    await DynamicMockData.list(_currentPage, PAGE_SIZE);
    this.setState(() {
      if (_currentPage > 1) {
        _listItems += _newItems;
      } else {
        _listItems = _newItems;
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: EasyRefresh(
        onRefresh: () async {
          _refresh();
        },
        onLoad: () async {
          _load();
        }, child: ListView.builder(itemCount: _listItems.length,
          itemBuilder: (context, index) {
            return DynamicItem(_listItems[index]['title'] as String,
                _listItems[index]['imageUrl'] as String,
                _listItems[index]['viewCount'] as int);
          }),
      ),
    );
  }
}
image.png
  • 注:EasyRefresh首次加载的时候不会主动load数据

解决方法

  • 1、设置firstRefresh为true
  • 2、在initState主动获取数据
@override
void initState() {
  // TODO: implement initState
  super.initState();
  _refresh();
}