gpt4 book ai didi

dart - 即使编码要使用不同的变量,也会使用 Widget 类的单个实例

转载 作者:IT王子 更新时间:2023-10-29 07:21:11 25 4
gpt4 key购买 nike

我想使用 Flutter 的 BottomNavigationBar,为此我创建了一个名为 BaseWidget 的类,该类将在用户点击该项目时更改。

class BaseWidget extends StatefulWidget {
final String title;

BaseWidget(this.title);

_BaseWidgetState createState() => _BaseWidgetState(this.title);
}

class _BaseWidgetState extends State<BaseWidget> {
final String title;

_BaseWidgetState(this.title);

@override
Widget build(BuildContext context) {
return Center(child: Text(title));
}
}

在上面的类中,我返回了 Center 小部件,其中子元素作为 Text 小部件。

class HomeWidget extends StatefulWidget {
_HomeWidgetState createState() => _HomeWidgetState();
}

class _HomeWidgetState extends State<HomeWidget> {
int pageIndex = 0;

final _home = BaseWidget('Home');
final _business = BaseWidget('Business');
final _school = BaseWidget('School');

@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Bottom Navigation Bar'),
),
body: choosePager(),
bottomNavigationBar: BottomNavigationBar(
currentIndex: pageIndex,
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home), title: Text('Home')),
BottomNavigationBarItem(
icon: Icon(Icons.business), title: Text('Business')),
BottomNavigationBarItem(
icon: Icon(Icons.school), title: Text('School')),
],
onTap: onTap,
),
),
);
}

void onTap(int index) {
setState(() {
this.pageIndex = index;
});
}

Widget choosePager() {
switch (pageIndex) {
case 0:
return _home;
break;
case 1:
return _business;
break;
case 2:
return _school;
break;
default:
return Text('Unknown');
break;
}
}
}

问题一:

每当用户点击 BottomNavigationBarItem 时,文本应更改为在 BaseWidget 的 构造函数中传递的相关字符串。但它只显示 Home,其余 2 个被忽略。

问题2:

我计划用 ListView 小部件替换 Center 小部件,以填充学校和企业列表,这些列表将以分页方式从网络 API 中获取。因此,我不想在点击 BottomNavigationBarItem 时再次重新初始化这些类,因为这会导致已经获取的数据丢失。为了防止数据丢失,我声明了 _home_business_school 属性,并在 choosePager() 方法中使用了这些属性.

最佳答案

您的代码有几个问题:

1- 真正的问题是您永远不会重建 BaseWidget。您构建了 3 个新的 BaseWidgets,但您只调用了 _home 小部件的 build,因为它是 choosePager 返回的第一个()。由于您没有在 HomeWidget build 中创建 _home_business_school , 无法构建其他 BaseWidget

2- 当您不需要为小部件存储任何状态/变量时,请使用Stateless 小部件。

3- 不要在您的状态的构造函数中执行任何操作。使用 initState https://docs.flutter.io/flutter/widgets/State/initState.html为此。

4- 尽可能使用 const 构造函数创建小部件。

5- 小部件构造函数采用命名参数。其中之一应该是关键。使用 super 调用基础构造函数。

考虑到这一点,代码应该是这样的:


class BaseWidget extends StatelessWidget {
final String title;

const BaseWidget({Key key, this.title}) : super(key: key);

@override
Widget build(BuildContext context) {
return Center(
child: Text(title),
);
}
}

class HomeWidget extends StatefulWidget {
_HomeWidgetState createState() => _HomeWidgetState();
}

class _HomeWidgetState extends State<HomeWidget> {
int pageIndex = 0;

@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Bottom Navigation Bar'),
),
body: choosePager(),
bottomNavigationBar: BottomNavigationBar(
currentIndex: pageIndex,
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home),
title: Text('Home'),
),
BottomNavigationBarItem(
icon: Icon(Icons.business),
title: Text('Business'),
),
BottomNavigationBarItem(
icon: Icon(Icons.school),
title: Text('School'),
),
],
onTap: onTap,
),
),
);
}

void onTap(int index) {
setState(() {
pageIndex = index;
});
}

Widget choosePager() {
Widget result;

switch (pageIndex) {
case 0:
result = BaseWidget(title: 'Home');
break;
case 1:
result = BaseWidget(title: 'Business');
break;
case 2:
result = BaseWidget(title: 'School');
break;
default:
result = Text('Unknown');
break;
}
return result;
}
}

编辑:对于您的示例,您可能希望从网络中获取一些数据并仅使用小部件来显示它。在这种情况下,创建一个新类(不是 Widget)来获取和保存数据,并且仅将 Widget 用于显示数据。

一些示例代码:

/// Silly class to fetch data
class DataClass {
static int _nextDatum = 0;
int _data;

DataClass();

Future<int> fetchData() async {
await Future.delayed(Duration(
milliseconds: 2000,
));
_data = _nextDatum++;
return _data;
}

int getData() {
return _data;
}
}

class BaseClass extends StatefulWidget {
final String title;
final DataClass data;

const BaseClass({Key key, this.title, this.data}) : super(key: key);

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

class _BaseClassState extends State<BaseClass> {
String title;
DataClass data;

@override
Widget build(BuildContext context) {
String dataStr = data == null ? ' - ' : '${data.getData()}';

return Center(
child: Text(
'$title: $dataStr',
),
);
}

@override
void initState() {
super.initState();
// initState gets called only ONCE
title = widget.title;
data = widget.data;
}

@override
void didUpdateWidget(BaseClass oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.data != oldWidget.data) {
data = widget.data;
}
if (widget.title != oldWidget.title) {
title = widget.title;
}
}
}

class HomeWidget extends StatefulWidget {
_HomeWidgetState createState() => _HomeWidgetState();
}

class _HomeWidgetState extends State<HomeWidget> {
int pageIndex = 0;
Map<String, DataClass> _dataMap = <String, DataClass>{};

@override
void initState() {
super.initState();
_init().then((result) {
// Since we need to rebuild the widget with the resulting data,
// make sure to use `setState`
setState(() {
_dataMap = result;
});
});
}

Future<Map<String, DataClass>> _init() async {
// this fetches the data only once
return <String, DataClass>{
'home': DataClass()..fetchData(),
'business': DataClass()..fetchData(),
'school': DataClass()..fetchData(),
};
}

@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Bottom Navigation Bar'),
),
body: choosePager(),
bottomNavigationBar: BottomNavigationBar(
currentIndex: pageIndex,
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home),
title: Text('Home'),
),
BottomNavigationBarItem(
icon: Icon(Icons.business),
title: Text('Business'),
),
BottomNavigationBarItem(
icon: Icon(Icons.school),
title: Text('School'),
),
],
onTap: onTap,
),
),
);
}

void onTap(int index) {
setState(() {
pageIndex = index;
});
}

Widget choosePager() {
Widget result;

switch (pageIndex) {
// it doesn't matter if you create a new BaseClass() a hundred times, flutter is optimized enough to not care. The `initState()` gets called only once. You're fetching the data only once.
case 0:
result = BaseClass(
title: 'Home',
data: _dataMap['home'],
);
break;
case 1:
result = BaseClass(
title: 'Business',
data: _dataMap['business'],
);
break;
case 2:
result = BaseClass(
title: 'School',
data: _dataMap['school'],
);
break;
default:
result = Text('Unknown');
break;
}
return result;
}
}

关于dart - 即使编码要使用不同的变量,也会使用 Widget 类的单个实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55562093/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com