这是我的代码,该代码调用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);
}
答案 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模式),也许您需要应用进行更多更改,但到目前为止,这些更改应该已经足够完成很多工作,但是请相信我,它将帮助您改善应用程序