英文:
JSON file not loading on Flutter
问题
我是Flutter新手,目前卡在我的JSON文件内容无法在模拟器上显示。没有错误显示,但也没有内容。如果我直接在我的代码块中包含内容,它可以正常工作。我无法找出问题所在。
以下是我的代码:
main.dart 代码
import 'package:emailapp/messagelist.dart';
import 'package:flutter/material.dart';
void main() => runApp(EmailApp());
class EmailApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.green,
),
home: MessageList(title: 'Muss Mailer APP'),
);
}
}
messagelist.dart
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class MessageList extends StatefulWidget {
final String title;
const MessageList({Key key, this.title}) : super(key: key);
@override
State<StatefulWidget> createState() => _MessageListState();
}
class _MessageListState extends State<MessageList> {
var messages = const [];
Future loadMessageList() async {
var content = await rootBundle.loadString('data/message.json');
print(content);
var collection = json.decode(content);
setState(() {
messages = collection;
});
}
void initState() {
loadMessageList();
super.initState();
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: ListView.separated(
separatorBuilder: (context, index) => Divider(),
itemCount: messages.length,
itemBuilder: (BuildContext context, int index) {
var message = messages[index];
return ListTile(
isThreeLine: true,
leading: CircleAvatar(child: Text('AJ')),
title: Text(message['subject']),
subtitle: Text(
message['body'],
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
);
},
),
);
}
}
message.json
[
{
"subject": "My First Message",
"body": "Hello Form the other side of life fellas.. and happy to meet you guys"
},
{
"subject": "My Second Message",
"body": "Hello Form the other side of life fellas.. and happy to meet you guys"
},
{
"subject": "My Third Message",
"body": "Hello Form the other side of life fellas.. and happy to meet you guys"
},
{
"subject": "My Fourth Message",
"body": "Hello Form the other side of life fellas.. and happy to meet you guys"
},
{
"subject": "My Fifth Message",
"body": "Hello Form the other side of life fellas.. and happy to meet you guys"
},
{
"subject": "My Sixth Message",
"body": "Hello Form the other side of life fellas.. and happy to meet you guys"
}
]
pubspec.yaml
assets:
- data/message.json
希望这可以帮助你解决问题。
英文:
I am new to Flutter, am currently stuck with my JSON file content not populating on my emulator. It shows no error, yet not displaying. If I include the content directly in my codeblock, it works fine. I can't spot the issue.
Below are my codes:
main.dart code
import 'package:emailapp/messagelist.dart';
import 'package:flutter/material.dart';
void main() => runApp(EmailApp());
class EmailApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.green
),
home: MessageList(title: 'Muss Mailer APP'),
);
}
}
messagelist.dart
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class MessageList extends StatefulWidget{
final String title;
const MessageList({Key key, this.title}) : super(key: key);
@override
State<StatefulWidget> createState()=>_MessageListState();
}
class _MessageListState extends State<MessageList>{
var messages=const [];
Future loadMessageList() async{
var content=await rootBundle.loadString('data/message.json');
print(content);
var collection=json.decode(content);
setState(() {
messages=collection;
});
}
void initstate() {
loadMessageList();
super.initState();
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: ListView.separated(
separatorBuilder: (context,index)=>Divider(),
itemCount: messages.length,
itemBuilder: (BuildContext context, int index){
var message=messages[index];
return ListTile(
isThreeLine: true,
leading: CircleAvatar( child: Text('AJ'),),
title: Text(message['subject']),
subtitle: Text(message['body'],maxLines: 2, overflow: TextOverflow.ellipsis,),
) ;
},
),
);
}
}
message.json
[ {
"subject":"My First Message",
"body":"Hello Form the other side of life fellas.. and happy to meet you guys"
},
{
"subject":"My Second Message",
"body":"Hello Form the other side of life fellas.. and happy to meet you guys"
},
{
"subject":"My Third Message",
"body":"Hello Form the other side of life fellas.. and happy to meet you guys"
},
{
"subject":"My Fourth Message",
"body":"Hello Form the other side of life fellas.. and happy to meet you guys"
},
{
"subject":"My Fifth Message",
"body":"Hello Form the other side of life fellas.. and happy to meet you guys"
},
{
"subject":"My Sixth Message",
"body":"Hello Form the other side of life fellas.. and happy to meet you guys"
}]
pubspec.yaml
assets:
# - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg
- data/message.json
答案1
得分: 1
"It's just a spelling mistake. It's not initstate
. Its initState
(S is capital).
void initState() {
loadMessageList();
super.initState();
}
```"
<details>
<summary>英文:</summary>
It's just a spelling mistake. It's not `initstate`. Its `initState` (**S** is capital).
void initState() {
loadMessageList();
super.initState();
}
</details>
# 答案2
**得分**: 1
我建议进行以下更改,以解决一些基本问题:
- 在`initState`方法中添加`@override`注释,并在`initState`方法的名称中使用`S`,如`@Crazy Lazy Cat`所建议的:
```dart
@override
void initState() {
loadMessageList();
super.initState();
}
- 移除
initState
内部使用setState
的部分,不建议在尚未构建的小部件上设置状态:
Future loadMessageList() async {
// 其他所有内容保持不变
messages = collection;
}
-
从消息中移除
const []
,因为它在initState
中已被替换。 -
由于
loadMessageList
是异步方法,您应该使用FutureBuilder
来实现此目的:
FutureBuilder(
future: loadMessageList,
builder: (context, snapshot) => snapshot.hasData ? your_widget() : Container(),
),
your_widget()
小部件指的是build
方法中的ListView.separated
小部件。
在定义ListView.separated
代码之前创建var messages = snapshot.data;
。
为了使此工作正常,您需要更改loadMessageList
中的代码:
Future loadMessageList() async {
// 其他所有内容保持不变
// messages = collection;
return collection;
}
现在不需要全局的messages
变量了。
英文:
I would suggest making the following changes, to resolve some basic issues:
- add Override notation to
initState
and useS
ininitState
name:
as suggested by@Crazy Lazy Cat
@override
void initState() {
loadMessageList();
super.initState();
}
- remove the use of
setState
inside theinitState
, it is not recommended to set state of a widget which has not been built yet:
Future loadMessageList() async{
// everything else, as it is
messages = collection;
}
-
remove
const []
from the messages, since it is replaced in theinitState
anyways. -
since the
loadMessageList
is async method you should useFutureBuilder
for this purpose:
FutureBuilder(
future: loadMessageList,
builder: (context, snapshot) => snapshot.hasData ? your_widget() : Container(),
),
your_widget()
widget refers to the ListView.separated
widget in the build method.
create var messages = snapshot.data;
before defining the ListView.separated
code.
for this to work you need to change the code in loadMessageList
:
Future loadMessageList() async {
// everything else, as it is
//messages = collection;
return collection;
}
No need of global messages
variable now.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论