我正在使用 API 调用来获取数据并在 ListView 中显示。
这是 FutureBuilder 类:
Widget futureBuilder() {
return FutureBuilder<List<Project>>(
future: _getProjects(),
builder: (context, snapshot) {
debugPrint('Builder');
switch (snapshot.connectionState) {
case ConnectionState.none:
case ConnectionState.waiting:
default:
if (snapshot.hasError)
return new Text('Error: ${snapshot.error}');
else
return listWidget(snapshot);
}
},
);
}
}
问题是,甚至在 _getProjects() 返回结果之前调用 debugPrint('Builder'),因此快照在我的 ListView 小部件中作为 null 传递。
这是 _getProjects() 类:
Future<List<Project>> _getProjects() async {
List<Project> projects = [];
String getProjects = "https://api.myjson.com/bins/1g3xpe";
var response = await http.get(getProjects);
Iterable list = json.decode(response.body);
projects = list.map((model) => Project.fromJson(model)).toList();
debugPrint('Size ' + projects.length.toString());
return projects;
}
完整代码如下:
class Projects extends StatefulWidget {
@override
ProjectState createState() => new ProjectState();
}
class ProjectState extends State {
Future<List<Project>> _getProjects() async {
List<Project> projects = [];
String getProjects = "https://api.myjson.com/bins/1g3xpe";
var response = await http.get(getProjects);
Iterable list = json.decode(response.body);
projects = list.map((model) => Project.fromJson(model)).toList();
debugPrint('Size ' + projects.length.toString());
return projects;
}
@override
Widget build(BuildContext context) {
return Scaffold(
primary: true,
appBar: EmptyAppBar(),
body: Column(
children: <Widget>[
headerWidget(),
futureBuilder()
],
),
);
}
Widget futureBuilder() {
return FutureBuilder<List<Project>>(
future: _getProjects(),
builder: (context, snapshot) {
debugPrint('Builder');
switch (snapshot.connectionState) {
case ConnectionState.none:
case ConnectionState.waiting:
default:
if (snapshot.hasError)
return new Text('Error: ${snapshot.error}');
else
return listWidget(snapshot);
}
},
);
}
}
Widget headerWidget() {
return Container(
padding: EdgeInsets.all(16.0),
color: Colors.blueAccent,
child: Container(
decoration: ShapeDecoration(
color: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(25.0)),
side: BorderSide(color: Colors.white))),
child: Row(
children: <Widget>[
Padding(padding: EdgeInsets.only(left: 12)),
Icon(Icons.arrow_back, color: Colors.black54),
Padding(padding: EdgeInsets.only(left: 12)),
Flexible(
fit: FlexFit.loose,
child: searchBar(),
),
Icon(
Icons.search,
color: Colors.black54,
),
Padding(padding: EdgeInsets.only(right: 12)),
],
)),
);
}
Widget searchBar() {
return Container(
height: 52,
alignment: Alignment.centerLeft,
padding: EdgeInsets.only(left: 12, right: 12),
child: TextField(
decoration: new InputDecoration.collapsed(
border: InputBorder.none,
filled: false,
hasFloatingPlaceholder: false,
hintText: 'Search here',
hintStyle: TextStyle(color: Colors.black54),
),
),
);
}
Widget listWidget(AsyncSnapshot<List<Project>> snapshot) {
return Scaffold(
body: ListView.builder(
itemBuilder: (BuildContext context, int index) {
listItem(snapshot.data[index]);
},
itemCount: snapshot.data.length));
}
Widget listItem(Project project) {
return Card(
elevation: 6.0,
child: Column(
children: <Widget>[Text('Project ID'), Text('Project Name')],
),
);
}
class EmptyAppBar extends StatelessWidget implements PreferredSizeWidget {
@override
Widget build(BuildContext context) {
return Container();
}
@override
Size get preferredSize => Size(0.0, 0.0);
}
更新: 我对 FutureBuilder 进行了一些更改:
Widget futureBuilder() {
return FutureBuilder<List<Project>>(
future: _getProjects(),
builder: (context, snapshot) {
debugPrint('Builder');
switch (snapshot.connectionState) {
case ConnectionState.done:
if (snapshot.hasError)
return new Text('Error: ${snapshot.error}');
else
return listWidget(snapshot);
break;
default:
debugPrint("Snapshot " + snapshot.toString());
}
},
);
}
我现在收到这个错误:
I/flutter ( 4054): _FutureBuilderState<List<Project>>#67dc4):
I/flutter ( 4054): A build function returned null.
I/flutter ( 4054): The offending widget is: FutureBuilder<List<Project>>
I/flutter ( 4054): Build functions must never return null. To return an empty space that causes the building widget to
I/flutter ( 4054): fill available room, return "new Container()". To return an empty space that takes as little room as
I/flutter ( 4054): possible, return "new Container(width: 0.0, height: 0.0)".
默认情况下,SnapShot 返回此快照 AsyncSnapshot>(ConnectionState.waiting, null, null)
最佳答案
您需要检查是否有AsyncSnapshot(快照)返回的数据。
添加这样的 if 语句:
if(snapshot.hasData && !snapshot.hasError) {
//rest of your code
}
else {
//show progress indicator or error...
}
关于android - FutureBuilder 不等待 future 完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56249715/
最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路
在我做的一些网络开发中,我有多个操作开始,比如对外部API的GET请求,我希望它们同时开始,因为一个不依赖另一个的结果。我希望事情能够在后台运行。我找到了concurrent-rubylibrary这似乎运作良好。通过将其混合到您创建的类中,该类的方法具有在后台线程上运行的异步版本。这导致我编写如下代码,其中FirstAsyncWorker和SecondAsyncWorker是我编写的类,我在其中混合了Concurrent::Async模块,并编写了一个名为“work”的方法来发送HTTP请求:defindexop1_result=FirstAsyncWorker.new.async.
一边学习thisRailscast我从Rack中看到了以下源代码:defself.middleware@middleware||=beginm=Hash.new{|h,k|h[k]=[]}m["deployment"].concat[[Rack::ContentLength],[Rack::Chunked],logging_middleware]m["development"].concatm["deployment"]+[[Rack::ShowExceptions],[Rack::Lint]]mendend我的问题是关于第三行。什么是传递block{|h,k|h[k]=[]}到Has
我不确定如何为我的搜索功能添加自动完成表单。"get"do%>nil%>我有一个具有自定义操作的Controllerdefquery@users=Search.user(params[:query])@article=Search.article(params[:query])end模型如下:defself.user(search)ifsearchUser.find(:all,:conditions=>['first_nameLIKE?',"%#{search}%"])elseUser.find(:all)endenddefself.article(search)ifsearchArt
编辑#2这是类(class)ControllerclassCoursesController编辑#1因此,根据下面Jagdeep的回答,我现在完成了以下操作:类(class).rbclassCoursecourse_modules_user.rbclassCourseModulesUsercourses_user.rbclassCoursesUser用户.rbclassUser迁移classCreateCoursesUsers但是,我遇到这样的错误原始问题所以这是previousquestion的延续,然而,这会偏离那个主题,所以这里是一个新的主题。在此之后,我大致得到了我想要开始工作
#!/usr/bin/envrubyrequire'optparse'options={}OptionParser.newdo|opts|opts.on("--languageLANGUAGE",["Ruby","JavaScript"])do|language|options[:language]=languageendend.parse!puts"Language:#{options[:language]}"如果我用./bin/example--languageRu运行它,它将输出:Language:Ruby我想禁用此自动完成/最接近的匹配行为,并在未提供确切名称时引发Option
我在nginx+unicorn后面运行一系列Rails/Sinatra应用程序,零停机部署。我喜欢这个设置,但Unicorn需要一段时间才能完成重新启动,所以我想在完成时发送某种通知。我能在Unicorn文档中找到的唯一回调与workerfork相关,但我认为这些回调对此不起作用。这是我从赏金中寻找的东西:老unicorn主人启动新主人,然后新主人开始它的worker,然后旧主人停止它的worker并让新主人接管。我想在交接完成后执行一些ruby代码。理想情况下,我不想为此实现任何复杂的流程监控。如果这是唯一的方法,那就这样吧。但在走那条路之前,我正在寻找更简单的选择。
当我对两个数组进行交集时,是否可以保证生成的顺序基于第一个数组的顺序?例如,如果我有a=[1,2,3]b=[3,2,1]可以a&b返回[3,2,1],而不是[1,2,3](这是什么我希望)?我在RDoc或Pickaxe的Array文档中找不到任何直接解决这个问题的内容。RubySpec有一个规范,它createsanarraywithelementsinordertheyarefirstencountered,但我是否应该假设YARVRuby会遵守该规范? 最佳答案 看起来这是一项有保证的功能。他们在revision39415中升级
我需要一个正则表达式来匹配一个字符串:只有数字0-9和空格所有数字必须相同应该至少有2位数字应该以数字开头和结尾匹配:11111111111111111111111111没有匹配项:1hasonlyonedigit11111hasspaceattheend11111hasspaceatbeginning12digitsaredifferent11:hasothercharacter我知道每个要求的正则表达式。这样我将使用4个正则表达式测试。我们可以在一个正则表达式中完成吗? 最佳答案 是的,它可以在一个正则表达式中完成:^(\d)(
我正在寻找一个很好的gem来处理注册工作流程的“完成百分比”管理。基本上,我的应用程序只允许用户使用电子邮件和密码进行注册,然后有一个LinkedIn样式的百分比指示器,该指示器会随着添加生日和性别等字段而增加。是否存在可帮助设置这样的流程的好gem?谢谢! 最佳答案 这是一个非常简单(而且很蹩脚)的解决方案的演示:在您的模型中,创建一个包含要完成的字段的数组,以及一个用于存储当前状态的整数字段,例如:classUserProc.new{|u|u.progress_status这样,每次用户更新其个人资料时,百分比都会更新(仅当低于