通过API最佳做法更新listview

时间:2019-11-20 12:07:40

标签: flutter dart

这是我的代码,该代码调用API以获取xml项目。 并按文章更新列表视图。

现在更改列表视图的变量后,我一次调用了setState()。

但是运行此代码。 setState()被无限调用,并不断更新。

我应该如何解决或什么是最佳做法?

class Article{
  String title;
  String url;
  Article() {}
}
List<Article> articles = [];

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;


  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    void _callApi() async{
      final response = await http.get('http://localhost/mamasoku/web/app_dev.php/api/byLatest/1/10');
      if (response.statusCode == 200) {

        var document = xml.parse(response.body);
        var items = document.findAllElements('item');
        print("item number:" + items.length.toString());
        items.forEach((var item) {
          var a = Article();
          a.title = item.findElements('title').single.text;
          a.url = item.findElements('url').single.text;
          articles.add(a);
        });
        setState(() => {});
      }
    }
    _callApi();

    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: BodyLayout(), 
    );
  }
}
class BodyLayout extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return _myListView(context);
  }
}
 Widget _myListView(BuildContext context) {


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

void onTapped(var index) {
  print(index);
}

2 个答案:

答案 0 :(得分:1)

setState()被无限调用的原因是setState()将调用build(BuildContext context)方法。

因此,您应该从build(BuildContext context)方法中删除setState(),并将_callApi()方法移至initState(),

像这样:

import 'package:flutter/material.dart';
import 'dart:ui' as ui;
import 'package:flutter/services.dart' show rootBundle;
import 'dart:async';
import 'dart:typed_data';

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class Article {
  String title;
  String url;

  Article() {}
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;
  List<Article> articles = [];

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    _callApi();
  }

  void _callApi() async {
//    final response = await http
//        .get('http://localhost/mamasoku/web/app_dev.php/api/byLatest/1/10');
//    if (response.statusCode == 200) {
//      var document = xml.parse(response.body);
//      var items = document.findAllElements('item');
//      print("item number:" + items.length.toString());
//      items.forEach((var item) {
//        var a = Article();
//        a.title = item.findElements('title').single.text;
//        a.url = item.findElements('url').single.text;
//        articles.add(a);
//      });
//
//    }

  ///  Analog network request
  Future.delayed(Duration(seconds: 10)).then((data){
    articles.add(Article()..title="test1"..url="www.123.com");
    articles.add(Article()..title="test2"..url="www.123.com");
    articles.add(Article()..title="test3"..url="www.123.com");
    articles.add(Article()..title="test4"..url="www.123.com");
    setState(() => {});
  });

  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: BodyLayout(articles),
    );
  }
}

class BodyLayout extends StatelessWidget {
  final List<Article> articles;

  BodyLayout(this.articles);

  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      itemCount: articles.length,
      itemBuilder: (context, index) {
        return ListTile(
          title: Text(articles[index].title),
        );
      },
    );
  }
}

void onTapped(var index) {
  print(index);
}

答案 1 :(得分:1)

您需要进行很多更改才能在此处应用最佳实践,您需要将模型,api调用,逻辑和视图分开,这样您可以应用“单一责任”模式,也建议使用BloC模式进行分隔从视图中选择逻辑,并创建一个通用类来处理所有api调用,因此在将来需要对api进行类似调用时,您无需重复代码(DRY模式),也许您需要应用进行更多更改,但到目前为止,这些更改应该已经足够完成很多工作,但是请相信我,它将帮助您改善应用程序