如何在Flutter中从http服务器构建动态列表? [英] how to build dynamic list from http server in flutter?

查看:128
本文介绍了如何在Flutter中从http服务器构建动态列表?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Flutter新手,从这里学到了很多东西。

Flutter newbie, learned a lot from here.

在通常情况下,人们会从Web服务器请求资源,服务器会返回对象数组:

In a common case, people will request resource from web servers and server return an array of objects:

[ { "key": "value"}, {"key": "value}...]

我们可以轻松地使用FutureBuilder。

We can easily handle this use FutureBuilder.

但是我有一台拥有海量数据的服务器,我必须从中获取资源方式:

But I have a server with massive data which I have to get resource in this way:


  1. 使用api查询记录计数,说 / resources / counts

  2. 查询用api记录几条记录,说 / resource?offset = 101& limit = 20以获得20条记录。

  3. 当用户向下滚动菜单时,将触发 / resource?offset = 121& limit = 20来获得另外20条记录。

所以我有一个列表,其中包含一些固定计数,但是资源有

So I have a list with fix count some kind, but the resource have to dynamic loaded from server. how to do that?

某些代码。

 @override
  Widget build(BuildContext context) {
    // _max == -1, request in progress.
    return _max == -1
        ? new CircularProgressIndicator()
        : ListView.builder(
            padding: const EdgeInsets.all(16.0),
            itemBuilder: (context, i) {
              return new FutureBuilder(
                future: _getFollowingContracts(),
                builder: (context, snapshot) {
                  if (i.isOdd) return new Divider();
                  switch (snapshot.connectionState) {
                    case ConnectionState.none:
                    case ConnectionState.waiting:
                    case ConnectionState.active:
                      return new Text('loading...');
                    case ConnectionState.done:
                      if (i.isOdd)
                        return new Divider(
                          height: 2.0,
                        );
                      final int index = i ~/ 2;
                      // when user scroll down here we got exception
                      // because only 20 records is available. 
                      // how to get another 20 records?
                      return _buildRow(_contracts[index]);
                  }
                },
              );
            },
            itemCount: _max * 2,
          );
  }


推荐答案

要实现此目的,您可以将 ScrollController 附加到 ListView 并监听其更改。在此侦听器中,当您处于滚动结尾时,您将获取更多数据并更新应用状态。

To implement this, you can attach a ScrollController to your ListView and listen its changes. In this listener when you are in the end of the scroll you fetch more data and update your app state.

示例:

以下代码是从这篇经充分说明的博客文章中提取的: https://marcinszalek.pl/flutter/infinite-dynamic-listview/

The following code is extracted from this well explained blog post: https://marcinszalek.pl/flutter/infinite-dynamic-listview/.

import 'dart:async';

import 'package:flutter/material.dart';

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

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

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

class _MyHomePageState extends State<MyHomePage> {
  List<int> items = List.generate(10, (i) => i);
  ScrollController _scrollController = new ScrollController();
  bool isPerformingRequest = false;

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

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

  _getMoreData() async {
    if (!isPerformingRequest) {
      setState(() => isPerformingRequest = true);
      List<int> newEntries = await fakeRequest(
          items.length, items.length + 10); //returns empty list
      if (newEntries.isEmpty) {
        double edge = 50.0;
        double offsetFromBottom = _scrollController.position.maxScrollExtent -
            _scrollController.position.pixels;
        if (offsetFromBottom < edge) {
          _scrollController.animateTo(
              _scrollController.offset - (edge - offsetFromBottom),
              duration: new Duration(milliseconds: 500),
              curve: Curves.easeOut);
        }
      }
      setState(() {
        items.addAll(newEntries);
        isPerformingRequest = false;
      });
    }
  }

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

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: AppBar(
        title: Text("Infinite ListView"),
      ),
      body: ListView.builder(
        itemCount: items.length + 1,
        itemBuilder: (context, index) {
          if (index == items.length) {
            return _buildProgressIndicator();
          } else {
            return ListTile(title: new Text("Number $index"));
          }
        },
        controller: _scrollController,
      ),
    );
  }
}

/// from - inclusive, to - exclusive
Future<List<int>> fakeRequest(int from, int to) async {
  return Future.delayed(Duration(seconds: 2), () {
    return List.generate(to - from, (i) => i + from);
  });
}

您将不得不将此代码适应您的情况(主要是通过更改 fakeRequest 方法以及如何渲染图块),但我认为它将为您提供主要思想。

You will have to adapt this code to your scenario (mainly by changing the fakeRequest method and how the tiles are rendered), but I think it will give you the main idea.

这篇关于如何在Flutter中从http服务器构建动态列表?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆