비동기 Builder를 사용하는 방법을 알아보자
먼저,
동기 - 요청과 결과가 동시에 일어난다.
비동기 - 요청과 결과가 동시에 일어나지 않는다.
class Info {
final String email;
final String nickname;
final String as_mail;
final String level;
Info({
required this.email,
required this.nickname,
required this.as_mail,
required this.level,
});
factory Info.fromJson(Map<String, dynamic> json) {
return Info(
email: json["email"],
nickname: json["nickname"],
as_mail: json["as_mail"],
level: json["level"],
);
}
}
late Future<List<Info>> info;
void initState() {
info = fetchInfo();
}
Future<List<Info>> fetchInfo() async {
var url =
'${Provider.of<SystemProvider>(context, listen: false).mainDomain}/api/member/my_account.php?email=' +
email;
print(url);
final response = await http.post(Uri.parse(url));
if (response.statusCode == 200) {
//만약 서버가 ok응답을 반환하면, json을 파싱합니다
//print('응답했다');
//print(json.decode(response.body));
Map<String, dynamic> map = json.decode(response.body);
List<dynamic> body = map["result"];
List<Info> allInfo =
body.map((dynamic item) => Info.fromJson(item)).toList();
nicknameController.text = allInfo[0].nickname.toString();
inputController.text = allInfo[0].as_mail.toString();
return allInfo;
} else {
//만약 응답이 ok가 아니면 에러를 던집니다.
throw Exception("네트워크 오류");
}
}
Container(
margin:
const EdgeInsets.only(left: 21, bottom: 23),
child: SizedBox(
width: MediaQuery.of(context).size.width - 111,
child: FutureBuilder<List<Info>>(
future: info,
builder: (context, snapshot) {
if (snapshot.hasData) {
return buildList(snapshot.data);
} else if (snapshot.hasError) {
print(snapshot.error);
return Text("${snapshot.error}에러!!");
}
return Container();
},
),
// as_mail == ""
// ? TextField(
// decoration: InputDecoration(
// hintText: "abcd123@gmail.com"),
// )
// : Text(as_mail),
),
// const Text(
// 'abcd123@gmail.com',
// style: GoogleFonts.notoSans(fontWeight: FontWeight.w400),
// ),
),
Widget buildList(snapshot) {
return Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextField(
style: GoogleFonts.notoSans(decorationThickness: 0),
enabled: sub_email_enabled,
focusNode: sub_focus_node,
controller: inputController,
decoration: InputDecoration(
enabledBorder: InputBorder.none,
disabledBorder: InputBorder.none,
focusColor: Colors.blue,
hoverColor: Colors.white)),
],
),
);
}
단순하게 정리
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'밑에 결과는 비동기 빌더로 가지고 오는 값',
style: TextStyle(fontSize: 20),
),
FutureBuilder(
future: _future(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
//해당 부분은 값을 아직 받아 오지 못했을때 실행되는 부분
if (snapshot.hasData == false) {
return CircularProgressIndicator(); // 로딩 구현
}
//에러 발생 시 반환 부분
else if (snapshot.hasError) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'Error: ${snapshot.error}',
style: TextStyle(fontSize: 15),
),
);
}
// 값을 정상적으로 받아오게 되면 다음 부분을 실행
else {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
snapshot.data.toString(),
style: TextStyle(fontSize: 15),
),
);
}
})
],
),
),
);
}
Future<String> _future() async {
await Future.delayed(Duration(seconds: 2));
return 'Call Value';
}
}