Flutter 有状态的代码问题。在 setstate 中放啥?
Posted
技术标签:
【中文标题】Flutter 有状态的代码问题。在 setstate 中放啥?【英文标题】:Flutter Stateful code problem. What to put in setstate?Flutter 有状态的代码问题。在 setstate 中放什么? 【发布时间】:2019-06-28 19:59:51 【问题描述】:我从不久前开始学习颤振。我非常了解编码,但我仍然有一些问题要理解有状态以及将什么放入创建状态。按照教程,我制作了这个应用程序,它加载一个带有地震信息的 json,并显示在一个侧面有滚动条的 ListView 中。现在我想让它成为一个有状态的小部件和 onrefresh 来更新来自 json 的值。这是我的代码(无状态) `
import 'package:flutter/material.dart';
import 'dart:async';
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:intl/intl.dart';
Map _quakes;
List _features; // oggesto list delle features
void main() async
_quakes = await getQuakes();
_features = _quakes["features"];
runApp(new MaterialApp(
theme: new ThemeData(
accentColor: Colors.red,
),
debugShowCheckedModeBanner: false,
color: Colors.red,
title: "Terremoti",
home: new Quakes(),
));
class Quakes extends StatelessWidget
@override
Widget build(BuildContext context)
return new Scaffold(
appBar: new AppBar(
title: new Text("Tutti i Terremoti ultime 24h"),
centerTitle: true,
backgroundColor: Colors.red,
),
body: new Center(
child: new Scrollbar(
child: RefreshIndicator(
onRefresh: getQuakes,
child: ListView.builder(
itemCount: _features.length,
padding: const EdgeInsets.all(15.0),
itemBuilder: (BuildContext context, position)
if (position.isOdd)
return new SizedBox(
height: 10.0,
child: new Center(
child: new Container(
margin: new EdgeInsetsDirectional.only(
start: 1.0, end: 1.0),
height: 2.5,
color: Colors.red,
),
),
);
final index = position ~/ 2;
var format = new DateFormat("dd MMM, yyyy, \n" + "HH:mm:ss");
//var dateString = format.format(format);
var date = format.format(
new DateTime.fromMillisecondsSinceEpoch(
_features[index]["properties"]["time"],
isUtc: true));
//creando le righe della listview
return new ListTile(
title: new Text(
"Magnitudo: $_features[index]["properties"]["mag"] \n $date",
style: new TextStyle(
fontSize: 21.0,
color: Colors.green,
fontWeight: FontWeight.w700),
),
subtitle: new Text(
"Luogo: $_features[index]["properties"]["place"]",
style: new TextStyle(
fontSize: 18.0,
),
),
);
),
),
)),
);
Future<Map> getQuakes() async
String apiUrl =
"https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_day.geojson";
http.Response response = await http.get(apiUrl);
return json.decode(response.body);
`
【问题讨论】:
【参考方案1】:提取代码以重新加载列表,并使其成为State
类的实例方法。接下来,允许列表为空(显示进度指示器)。最后从initState
调用reload方法。
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:intl/intl.dart';
void main() async
runApp(MaterialApp(
theme: ThemeData(
accentColor: Colors.red,
),
debugShowCheckedModeBanner: false,
color: Colors.red,
title: 'Terremoti',
home: Quakes(),
));
class Quakes extends StatefulWidget
@override
State createState() => QuakesState();
class QuakesState extends State<Quakes>
DateFormat format = DateFormat('dd MMM, yyyy, \nHH:mm:ss');
List _features;
@override
void initState()
super.initState();
reload();
Future<void> reload() async
final Map quakes = await getQuakes();
setState(()
_features = quakes['features'];
);
@override
Widget build(BuildContext context)
return Scaffold(
appBar: AppBar(
title: const Text('Tutti i Terremoti ultime 24h'),
centerTitle: true,
backgroundColor: Colors.red,
),
body: Center(
child: _features == null
? const CircularProgressIndicator()
: Scrollbar(
child: RefreshIndicator(
onRefresh: reload,
child: ListView.builder(
itemCount: _features.length,
padding: const EdgeInsets.all(15.0),
itemBuilder: (BuildContext context, position)
if (position.isOdd)
return SizedBox(
height: 10.0,
child: Center(
child: Container(
margin: const EdgeInsetsDirectional.only(
start: 1.0,
end: 1.0,
),
height: 2.5,
color: Colors.red,
),
),
);
final int index = position ~/ 2;
final String date = format.format(
DateTime.fromMillisecondsSinceEpoch(
_features[index]['properties']['time'],
isUtc: true));
//creando le righe della listview
return ListTile(
title: Text(
"Magnitudo: $_features[index]["properties"]["mag"] \n $date",
style: const TextStyle(
fontSize: 21.0,
color: Colors.green,
fontWeight: FontWeight.w700),
),
subtitle: Text(
"Luogo: $_features[index]["properties"]["place"]",
style: const TextStyle(
fontSize: 18.0,
),
),
);
),
),
),
),
);
Future<Map> getQuakes() async
final http.Response response = await http.get(
'https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_day.geojson');
return json.decode(response.body);
【讨论】:
非常感谢。我将检查代码以理解它。但是如何更改滚动条的颜色甚至其他一些属性?比如宽度或者在它消失之前应该保留多少时间? 通常,使用材料设计小部件,这些类型的设置由材料设计规范设置,颤振小部件遵循它们。如果您查看ScrollBar
的源代码,您会发现它们是文件const double _kScrollbarThickness = 6.0; const Duration _kScrollbarFadeDuration = Duration(milliseconds: 300); const Duration _kScrollbarTimeToFade = Duration(milliseconds: 600);
顶部的常量。顺便说一句,似乎很少使用带有ListView
的滚动条,它会自行滚动,但没有关于其运动范围的反馈。
非常感谢。您的帮助真的很有帮助。
如果有帮助,别忘了“接受”答案。
一些问题... InitState 每次应用打开时都会调用?甚至从只是背景不完全开始? Future以上是关于Flutter 有状态的代码问题。在 setstate 中放啥?的主要内容,如果未能解决你的问题,请参考以下文章
从另一个有状态小部件调用一个有状态小部件中的方法 - Flutter
ReactJs:在使用动态 Taglist 时使用道具设置初始状态