【问题标题】:Flutter - how to parse paged JSON data into ListView?Flutter - 如何将分页的 JSON 数据解析为 ListView?
【发布时间】:2020-01-25 02:16:13
【问题描述】:

在使用搜索视图时,我正在尝试将 JSON 数据解析为 Listview。我目前正在使用它,我的问题是来自我的url 的数据是paginated。当我只做一组数据时,没有问题,但我想不通如何做多个数据。我已经尝试使用for loop 来浏览所有页面,但我无法将其放入我的response 以提取数据。基本上我想遍历所有分页的 url,然后从整个 url 列表中获取响应数据。不知道如何实现这一点。有什么帮助吗?

带有 For 循环的代码部分

Future<List<Coins>> fetchList() async {

for (i = 0; i < 25; i++){
url = 'www.example.com/page=$i';
}

var response = await http.get(url);

var coins = List<Coins>();

if (response.statusCode == 200) {
  var coinsJSON = json.decode(response.body);
  for (var coinJSON in coinsJSON) {
    coins.add(Coins.fromJson(coinJSON));
  }
}
return coins;
}

完整的类代码

class SearchBar extends SearchDelegate<String> {
List<Coins> _coins = List<Coins>();

Future<List<Coins>> fetchList() async {
var url = 'www.example.com/page=1';
var response = await http.get(url);

var coins = List<Coins>();

if (response.statusCode == 200) {
  var coinsJSON = json.decode(response.body);
  for (var coinJSON in coinsJSON) {
    coins.add(Coins.fromJson(coinJSON));
  }
}
return coins;
}

@override
Widget buildSuggestions(BuildContext context) {
// What to display while searching
SearchBar().fetchList().then((value) {
  _coins.clear();
  _coins.addAll(value);
});


final suggestionList = query.isEmpty ? 
[]:_coins.where((item)=>item.name.toLowerCase().startsWith(query.toLowerCase())).toList();

return ListView.builder(
    itemCount: suggestionList.length,
    itemBuilder: (context, index) {
      return ListTile(
        title: Text(suggestionList[index].name),
      );
    });
}
}

【问题讨论】:

    标签: json listview parsing flutter pagination


    【解决方案1】:

    你可以使用包https://pub.dev/packages/incrementally_loading_listview
    它可以按页加载数据,您可以设置每页的数量并使用_loadingMore函数控制何时加载更多数据

    在您的情况下,在 _loadMoreItems() 中,您可以为下一页调用 api 并添加到项目列表

    代码sn-p

      bool _loadingMore;
      bool _hasMoreItems;
      int _maxItems = 30;
      int _numItemsPage = 10;
      Future _initialLoad;
    
      Future _loadMoreItems() async {
        final totalItems = items.length;
        await Future.delayed(Duration(seconds: 3), () {
          for (var i = 0; i < _numItemsPage; i++) {
            items.add(Item('Item ${totalItems + i + 1}'));
          }
        });
    
        _hasMoreItems = items.length < _maxItems;
      }
    

    完整代码

    import 'dart:async';
    
    import 'package:flutter/material.dart';
    import 'package:incrementally_loading_listview/incrementally_loading_listview.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      // This widget is the root of your application.
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: MyHomePage(title: 'Flutter Demo Home Page'),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      MyHomePage({Key key, this.title}) : super(key: key);
    
      // This widget is the home page of your application. It is stateful, meaning
      // that it has a State object (defined below) that contains fields that affect
      // how it looks.
    
      // This class is the configuration for the state. It holds the values (in this
      // case the title) provided by the parent (in this case the App widget) and
      // used by the build method of the State. Fields in a Widget subclass are
      // always marked "final".
    
      final String title;
    
      @override
      _MyHomePageState createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      List<Item> items;
      bool _loadingMore;
      bool _hasMoreItems;
      int _maxItems = 30;
      int _numItemsPage = 10;
      Future _initialLoad;
    
      Future _loadMoreItems() async {
        final totalItems = items.length;
        await Future.delayed(Duration(seconds: 3), () {
          for (var i = 0; i < _numItemsPage; i++) {
            items.add(Item('Item ${totalItems + i + 1}'));
          }
        });
    
        _hasMoreItems = items.length < _maxItems;
      }
    
      @override
      void initState() {
        super.initState();
        _initialLoad = Future.delayed(Duration(seconds: 3), () {
          items = List<Item>();
          for (var i = 0; i < _numItemsPage; i++) {
            items.add(Item('Item ${i + 1}'));
          }
          _hasMoreItems = true;
        });
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          backgroundColor: Colors.yellow,
          appBar: AppBar(
            title: Text(widget.title),
          ),
          body: FutureBuilder(
              future: _initialLoad,
              builder: (context, snapshot) {
                switch (snapshot.connectionState) {
                  case ConnectionState.waiting:
                    return Center(child: CircularProgressIndicator());
                  case ConnectionState.done:
                    return IncrementallyLoadingListView(
                      hasMore: () => _hasMoreItems,
                      itemCount: () => items.length,
                      loadMore: () async {
                        // can shorten to "loadMore: _loadMoreItems" but this syntax is used to demonstrate that
                        // functions with parameters can also be invoked if needed
                        await _loadMoreItems();
                      },
                      onLoadMore: () {
                        setState(() {
                          _loadingMore = true;
                        });
                      },
                      onLoadMoreFinished: () {
                        setState(() {
                          _loadingMore = false;
                        });
                      },
                      loadMoreOffsetFromBottom: 2,
                      itemBuilder: (context, index) {
                        final item = items[index];
                        if ((_loadingMore ?? false) && index == items.length - 1) {
                          return Column(
                            children: <Widget>[
                              ItemCard(item: item),
                              Card(
                                child: Padding(
                                  padding: const EdgeInsets.all(16.0),
                                  child: Column(
                                    children: <Widget>[
                                      Row(
                                        crossAxisAlignment:
                                        CrossAxisAlignment.start,
                                        children: <Widget>[
                                          Container(
                                            width: 60.0,
                                            height: 60.0,
                                            color: Colors.grey,
                                          ),
                                          Padding(
                                            padding: const EdgeInsets.fromLTRB(
                                                8.0, 0.0, 0.0, 0.0),
                                            child: Container(
                                              color: Colors.grey,
                                              child: Text(
                                                item.name,
                                                style: TextStyle(
                                                    color: Colors.transparent),
                                              ),
                                            ),
                                          )
                                        ],
                                      ),
                                      Padding(
                                        padding: const EdgeInsets.fromLTRB(
                                            0.0, 8.0, 0.0, 0.0),
                                        child: Container(
                                          color: Colors.grey,
                                          child: Text(
                                            item.message,
                                            style: TextStyle(
                                                color: Colors.transparent),
                                          ),
                                        ),
                                      )
                                    ],
                                  ),
                                ),
                              ),
                            ],
                          );
                        }
                        return ItemCard(item: item);
                      },
                    );
                  default:
                    return Text('Something went wrong');
                }
              }),
        );
      }
    }
    
    class ItemCard extends StatelessWidget {
      const ItemCard({
        Key key,
        @required this.item,
      }) : super(key: key);
    
      final Item item;
    
      @override
      Widget build(BuildContext context) {
        return GestureDetector(
          child: Card(
            child: Padding(
              padding: const EdgeInsets.all(16.0),
              child: Column(
                children: <Widget>[
                  Row(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: <Widget>[
                      Image.network(item.avatarUrl),
                      Expanded(
                        child: Padding(
                          padding: const EdgeInsets.fromLTRB(8.0, 0.0, 0.0, 0.0),
                          child: Text(item.name),
                        ),
                      )
                    ],
                  ),
                  Padding(
                    padding: const EdgeInsets.fromLTRB(0.0, 8.0, 0.0, 0.0),
                    child: Text(item.message),
                  )
                ],
              ),
            ),
          ),
          onTap: () => Navigator.of(context).push(
            MaterialPageRoute(builder: (context) => ItemDetailsPage(item)),
          ),
        );
      }
    }
    
    class ItemDetailsPage extends StatelessWidget {
      final Item item;
      const ItemDetailsPage(this.item);
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
            backgroundColor: Colors.yellow,
            appBar: AppBar(
              title: Text(item.name),
            ),
            body: Container(
              child: Text(item.message),
            ));
      }
    }
    
    class Item {
      final String name;
      final String avatarUrl = 'http://via.placeholder.com/60x60';
      final String message =
          'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.';
    
      Item(this.name);
    }
    

    【讨论】:

      猜你喜欢
      • 2020-01-05
      • 2016-03-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-13
      • 2018-11-21
      相关资源
      最近更新 更多