flutter - StatefullWidget 每次都重新初始化
问题描述
我试图简单地从 API 打印类别列表。我创建了我的 statefull 小部件,它工作正常。
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:playlife/models/Category.dart';
import 'package:playlife/globals.dart';
class CategoryMenu extends StatefulWidget {
List<Category> list = List();
CategoryMenu({Key key}) : super(key: key);
@override
_CategoryMenuState createState() => _CategoryMenuState();
}
class _CategoryMenuState extends State<CategoryMenu> {
var isLoading = false;
_fetchData() async {
setState(() {
isLoading = true;
});
final response =
await http.get(baseApiUrl + '/v2/5ebc29a22e000054009f4261');
if (response.statusCode == 200) {
widget.list = (json.decode(response.body) as List)
.map((data) => new Category.fromJson(data))
.toList();
setState(() {
isLoading = false;
});
} else {
throw Exception('Failed to load categories');
}
}
@override
void initState() {
super.initState();
if(widget.list.length == 0) {
_fetchData();
}
}
@override
Widget build(BuildContext context) {
return isLoading
? Center(
child: CircularProgressIndicator(),
)
: ListView.builder(
itemCount: widget.list.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text(widget.list[index].title, style: TextStyle(color: Colors.white)),
);
});
}
}
在我的主页中,我只需将其添加到抽屉下
结束
rawer: Drawer( ....
Row (
children: [
Expanded(
child: SizedBox(
height: 300.0,
child: CategoryMenu(),
)
),
],
),
再次,这工作正常。当我第一次打开菜单时,API 被称为 widget.list 被填充。下次我打开菜单时,不会调用 API,因为 widget.list 已经存在。现在我正在尝试将 Drawer 下的所有内容移动到无状态小部件中以重用它。
所以我只是创建了一个 StatelessWidget ,它与我在 endDrawer 之后的完全一样
class Menu extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Drawer(
// Add a ListView to the drawer. This ensures the user can scroll
// through the options in the drawer if there isn't enough vertical
// space to fit everything.
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.topRight,
colors: [backgroundColor, backgroundColorTo])),
child: ListView(
// Important: Remove any padding from the ListView.
padding: EdgeInsets.zero,
children: <Widget>[
Container(
height: 80.0,
child: DrawerHeader(
child: Text('', style: TextStyle(color: Colors.white)),
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.topRight,
colors: [backgroundColor, backgroundColorTo])),
margin: EdgeInsets.all(0.0),
padding: EdgeInsets.all(0.0)
),
),
ListTile(
title: Text('Discover', style: TextStyle(color: Colors.white)),
onTap: () {
// Update the state of the app
// ...
// Then close the drawer
Navigator.pop(context);
},
),
ListTile(
title: Text('Login', style: TextStyle(color: Colors.white)),
onTap: () {
// Update the state of the app
// ...
// Then close the drawer
Navigator.pop(context);
},
),
Row (
children: [
Expanded(
child: SizedBox(
height: 300.0,
child: CategoryMenu(),
)
),
],
),
],
),
),
);
}
}
这就是问题开始的地方。每次我打开菜单都会调用 API。如果我在 initState 中打印 widget.list,我总是得到一个空列表。我还尝试使用 AsyncMemoizer,如下所述:https ://medium.com/saugo360/flutter-my-futurebuilder-keeps-firing-6e774830bc2 并且还尝试对菜单使用 statefull 小部件。
我不明白为什么会这样。
解决方案
您应该在主页的initState中调用_fetchData方法,如下所示:
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
List<Category> list =[];
var isLoading = false;
_fetchData() async {
//Do your Http call
}
@override
void initState() {
super.initState();
_fetchData();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: YourBody(),
drawer: Drawer(
),
);
}
}
推荐阅读
- javascript - 如何打破 XSS 的双引号?
- java - 将 Steam 响应转换为 java graphql API 中 DatafetcherResult 对象的一部分
- ansible-inventory - 一个密码失败时的ansible库存尝试不同
- ios - TextField 在其他视图中通过协议更改值,如果用户更改 textField 输入如何存储值
- react-native - React Native Fetch data from api issue
- node.js - heroku push 卡住了
- powershell - 我正在做 3 个连续的 foreach 循环,它花费了很多时间?有没有更好的方法来解决这个难题?
- javascript - 使用 Express 异步错误的 Stange 行为
- javascript - JavaScript/DOM:MutationObserver 检测 DOM 树中任何位置的 `lang` 属性的变化
- unit-testing - 如何在 test.check 中生成随机电子邮件地址?