- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
编辑:我编辑了下面的代码,以突出获取数据的方法以及构建火车估计的小部件(用 "API_URL 替换沿途的任何 API 信息“
和 “API_STOP_ID”
)。我希望这能更好地帮助我们解决问题!我真的很感激任何人可以提供的任何信息——我一直在为这个项目努力工作!再次感谢大家!
原帖:我有一个 ListTiles 的 ListView,每个 ListView 都有一个尾随小部件,它在一个新的文本小部件中构建火车到达估计。这些尾随的小部件每五秒更新一次(由 print 语句证明)。当应用程序从火车的 API 获取数据时,它会显示一个“无数据”文本小部件,该小部件由 _buildEstimatesNull() 构建。
但是,问题是即使应用程序已完成获取数据并且 _isLoading = false
仍显示“无数据”(由 print 语句证明)。尽管如此,即使解决了这个问题,列车估计也会很快过时,因为尾随的小部件每五秒自行更新一次,但这不会反射(reflect)在实际的应用程序中,因为小部件是在页面加载时构建的。因此,我需要一种方法来在获取新信息时重建那些尾随的小部件。
有没有办法让 Flutter 也每五秒自动重建一次 ListTile 的尾随小部件(或者每当 _buildEstimatesS1 更新/尾随小部件的内部更新时)?
class ShuttleApp extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return new ShuttleState();
}
}
class ShuttleState extends State<ShuttleApp> {
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: new HomeScreen(),
);
}
}
class HomeScreen extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return new HomeState();
}
}
class HomeState extends State<HomeScreen> {
var _isLoading = true;
void initState() {
super.initState();
_fetchData();
const fiveSec = const Duration(seconds: 5);
new Timer.periodic(fiveSec, (Timer t) {
_fetchData();
});
}
var arrivalsList = new List<ArrivalEstimates>();
_fetchData() async {
arrivalsList.clear();
stopsList.clear();
final url = "API_URL";
print("Fetching: " + url);
final response = await http.get(url);
final busesJson = json.decode(response.body);
if (busesJson["service_id"] == null) {
globals.serviceActive = false;
} else {
busesJson["ResultSet"]["Result"].forEach((busJson) {
if (busJson["arrival_estimates"] != null) {
busJson["arrival_estimates"].forEach((arrivalJson) {
globals.serviceActive = true;
final arrivalEstimate = new ArrivalEstimates(
arrivalJson["route_id"], arrivalJson["arrival_at"], arrivalJson["stop_id"]
);
arrivalsList.add(arrivalEstimate);
});
}
});
}
setState(() {
_isLoading = false;
});
}
Widget _buildEstimateNull() {
return new Container(
child: new Center(
child: new Text("..."),
),
);
}
Widget _buildEstimateS1() {
if (globals.serviceActive == false) {
print('serviceNotActive');
_buildEstimateNull();
} else {
final String translocStopId = "API_STOP_ID";
final estimateMatches = new List<String>();
arrivalsList.forEach((arrival) {
if (arrival.stopId == translocStopId) {
estimateMatches.add(arrival.arrivalAt);
}
});
estimateMatches.sort();
if (estimateMatches.length == 0) {
print("zero");
return _buildEstimateNull();
} else {
return new Container(
child: new Center(
child: new Text(estimateMatches[0]),
),
);
}
}
}
@override
Widget build(BuildContext context) {
return new Scaffold(
backgroundColor: const Color(0xFF171717),
appBar: new AppBar(),
body: new DefaultTextStyle(
style: new TextStyle(color: const Color(0xFFaaaaaa),),
child: new ListView(
children: <Widget>[
new ListTile(
title: new Text('S1: Forest Hills',
style: new TextStyle(fontWeight: FontWeight.w500, fontSize: 20.0)),
subtitle: new Text('Orange Line'),
contentPadding: new EdgeInsets.symmetric(vertical: 16.0, horizontal: 16.0),
trailing: _isLoading ? _buildEstimateNull() : _buildEstimateS1(),
),
],
),
)
);
}
class ArrivalEstimates {
final String routeId;
final String arrivalAt;
final String stopId;
ArrivalEstimates(this.routeId, this.arrivalAt, this.stopId);
}
非常感谢您提供的任何帮助!我真的 super 感谢! :)
最佳答案
有几种方法可以解决这个问题。但是,如果不查看更多代码,就很难判断发生了什么——特别是您如何获取数据以及您正在使用它做什么。但我想无论如何我都能给你一个足够的答案。
这样做的简单方法是:
setState(() => this.listData = data);
。对 setState 的调用告诉小部件它需要重建。setState(() => this.itemData = data);
。这意味着多次调用 API 等。#1 的优点是你可以批处理 API 调用,而#2 的优点是你的构建整体变化较小(尽管 flutter 的工作方式,这将是非常小的)......所以我可能会如果可能的话,选择#1。
但是,还有更好的方法!
更好的方法是使用某种 API 管理器(或任何您想要的名称)来处理与您的 API 的通信。它可能会在您的小部件树中位于更高的位置,并且会以您想要的任何逻辑启动/停止。根据小部件树在多远的位置,您可以将它传递给每个 child ,或者更可能将它保存在一个 InheritedWidget 中,然后可以使用它从每个列表元素或整个列表中检索它。
API 管理器会提供各种 streams - 根据您的 API,使用一堆命名字段/方法或使用 getStream(id) 类型的结构。
然后,在您的各种列表元素中,您将使用 StreamBuilder基于数据构建每个元素的小部件 - 通过使用 StreamBuilder,您可以获得一个 ConnectionState 对象,该对象让您知道流是否已接收到任何数据,因此您可以选择显示 isLoading 类型的小部件而不是显示数据的小部件.
通过使用这种更高级的方法,您可以获得:
编辑:根据 OP 的评论,他们已经或多或少地实现了第一个建议。但是,代码存在一些问题。我将在下面列出它们,并且我已经发布了一些更改的代码。
arrivalsList
应该在每次完成新构建时被替换,而不是简单地被更改。这是因为 dart 会比较列表,如果找到相同的列表,它不一定会比较所有元素。此外,虽然在函数中间更改它不一定会导致问题,但通常最好使用局部变量然后在最后更改值。请注意,该成员实际上是在 setState 中设置的。return _buildEstimateNull();
错过了返回。代码如下:
class HomeState extends State<HomeScreen> {
var _isLoading = true;
void initState() {
super.initState();
_fetchData();
const fiveSec = const Duration(seconds: 5);
new Timer.periodic(fiveSec, (Timer t) {
_fetchData();
});
}
var arrivalsList = new List<ArrivalEstimates>();
_fetchData() async {
var arrivalsList = new List<ArrivalEstimates>(); // *********** #1
stopsList.clear();
final url = "API_URL";
print("Fetching: " + url);
final response = await http.get(url);
final busesJson = json.decode(response.body);
if (busesJson["service_id"] == null) {
print("no service id");
globals.serviceActive = false;
} else {
busesJson["ResultSet"]["Result"].forEach((busJson) {
if (busJson["arrival_estimates"] != null) {
busJson["arrival_estimates"].forEach((arrivalJson) {
globals.serviceActive = true;
final arrivalEstimate = new ArrivalEstimates(
arrivalJson["route_id"], arrivalJson["arrival_at"], arrivalJson["stop_id"]
);
arrivalsList.add(arrivalEstimate);
});
}
});
}
setState(() {
_isLoading = false;
this.arrivalsList = arrivalsList; // *********** #1
});
}
Widget _buildEstimateNull() {
return new Container(
child: new Center(
child: new Text("..."),
),
);
}
Widget _buildEstimateS1() {
if (globals.serviceActive == false) {
print('serviceNotActive');
return _buildEstimateNull(); // ************ #2
} else {
final String translocStopId = "API_STOP_ID";
final estimateMatches = new List<String>();
print("arrivalsList length: ${arrivalsList.length}");
arrivalsList.forEach((arrival) {
if (arrival.stopId == translocStopId) {
print("Estimate match found: ${arrival.stopId}");
estimateMatches.add(arrival.arrivalAt);
}
});
estimateMatches.sort();
if (estimateMatches.length == 0) {
print("zero");
return _buildEstimateNull();
} else {
return new Container(
child: new Center(
child: new Text(estimateMatches[0]),
),
);
}
}
}
@override
Widget build(BuildContext context) {
return new Scaffold(
backgroundColor: const Color(0xFF171717),
appBar: new AppBar(),
body: new DefaultTextStyle(
style: new TextStyle(color: const Color(0xFFaaaaaa),),
child: new ListView(
children: <Widget>[
new ListTile(
title: new Text('S1: Forest Hills',
style: new TextStyle(fontWeight: FontWeight.w500, fontSize: 20.0)),
subtitle: new Text('Orange Line'),
contentPadding: new EdgeInsets.symmetric(vertical: 16.0, horizontal: 16.0),
trailing: _isLoading ? _buildEstimateNull() : _buildEstimateS1(),
),
],
),
)
);
}
关于dart - 发生更改时如何在 Flutter 中重建小部件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51033222/
我想向一些用户公开一个 Web 部件,但不是所有用户。如何在“添加 Web 部件”弹出窗口中显示或隐藏 Web 部件?我想通过代码来做到这一点,我希望使用 SharePoint 角色来实现这一点。 最
我无法创建两个以上的 StatusBar 部分: HWND hStatusBar = CreateWindowEx(0, STATUSCLASSNAME, "", WS_CHILD | WS_VISI
使用 SharePoint 2007,如何在编辑页面模式下允许将 CEWP 添加到“添加 Web 部件”对话框的选择菜单?目前,我只能添加公告、日历、链接、共享文档、任务,但我无法添加 CEWP。我可
哪个 Web 部件以及如何配置它以查看来自不同网站集的列表? 请注意,我不想查看页面,而是查看列表。例如,在单独的网站集下查看来自不同团队网站的公告。 预先感谢您的帮助。 最佳答案 Data Form
以下是我在 FeatureDeactivation 事件处理程序中添加的代码片段。我无法获得删除 System.Web.UI.WebControls.WebParts 类型的 webpart 的解决方
我一直在尝试跟踪来自以下方面的信息: Long URL clipped to stop breaking the page 和 http://msdn.microsoft.com/en-us/libr
我想创建一个自定义 Web 部件,它具有 1 个以上的筛选器 Web 部件,并且可以在运行时/设计时连接到报表查看器 Web 部件(集成模式)。 我为此搜索了很多,但找不到一种方法来让单个 Web 部
我正在尝试创建一个 Web 部件,使用户无需离开 AllItems.aspx 页面即可编辑项目。 Web 部件应具有与 EditForm.aspx 页面类似的功能。 我已经使用 ConnectionC
这些年发布的许多应用程序都有新的 GUI 部件。iTunes 或 Twitter.app 中垂直布局的最小、最大和关闭按钮(但最新的具有默认布局),Safari 和终端中的选项卡控件,GarageBa
在具有数据库依赖性的 WSS3 或 MOSS2007 中部署 Web 部件的最佳方法是什么? .wsp 是否应该包含创建数据库的代码,我应该将 .wsp 封装在另一个处理数据库创建的安装程序中,还是应
我在我们位于 http://sharepoint:12345 的 moss 服务器上创建了一个新的共享点站点并毫无问题地向其添加了 CQWP。 我有一个指向同一台服务器的域名。所以我指向了http:/
在官方 Office 2007 站点中有许多对筛选器 Web 部件的引用。当我尝试添加其中之一时,我的 Sharepoint 中的 Web 部件列表没有显示任何筛选器 Web 部件。 如果有人遇到相同
我被要求在 Sharepoint 中创建一个 Web 部件,列出用户在网站集中访问的最后 10 个文档。 我的客户想要一种快速的方式让用户访问文档,这样他们就不必翻遍文件夹结构来查找文档,因为大多数时
我需要使用 C# 以编程方式将 SharePoint Web 部件“站点用户”添加到页面。 我知道如何添加 Web 部件,但如何从 Share Point 获取“站点用户”Web 部件?我不知道如何实
我正在使用 MEF 在我的应用程序中加载插件。一切正常,但我希望在将新部件放入我的应用程序文件夹时发现它们。这可能吗? DirectoryCatalog 有一个 Changed 事件,但我不确定它是如
我有一个 Winforms 桌面应用程序正在加载具有相同接口(interface)类型的多个 MEF 部件。 问题:当我尝试加载多个相同类型时,出现以下异常: 组成保持不变。由于以下错误,更改被拒绝:
我有一个内容查询 Web 部件,它按内容类型对网站集进行查询。我已按内容类型对其进行了分组,因此我有: -- Agenda (Content Type) ----Agenda #1 ----Agend
考虑以下 SharePoint 站点层次结构: - Site Collection - Site1 - Subsite1 - AnotherSubsite1
好吧,在我的 SharePoint (2013) 网站中,我制作了一个简单的 JavaScript Web 部件,每五分钟刷新一次页面。我去调整时间,在刷新前输入等待时间的地方退格,然后不假思索地退出
我不知道 Sharepoint 脚本,我的同事也不知道 JavaScript。他使用了他在 http://www.wonderlaura.com/Lists/Posts/Post.aspx?ID=22
我是一名优秀的程序员,十分优秀!