Future Builder
import 'dart:math';
import 'package:flutter/material.dart';
class HomeScreen extends StatefulWidget {
const HomeScreen({Key? key}) : super(key: key);
@override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
final textStyle = const TextStyle(
fontSize: 20.0,
);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Padding(
padding: const EdgeInsets.all(8.0),
child: FutureBuilder(
builder: (context, snapshot) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
'Future Builder',
style: textStyle.copyWith(
fontWeight: FontWeight.w700,
fontSize: 30.0,
),
),
Text(
'ConState : ${snapshot.connectionState}',
),
Text(
'Data : ${snapshot.data}',
),
Text(
'Error : ${snapshot.error}',
),
],
);
},
),
),
);
}
Future<int> getNumber() async {
await Future.delayed(
Duration(seconds: 3),
);
final random = Random();
return random.nextInt(10);
}
}
- builder만 넣어줄 경우 connectionState는 none이 출력된다.
- FutureBuilder에 future 값을 넣어주면 connectionState 값이 waiting에서 done으로 바뀌고 Data값은 랜덤 함수에 의해 3이 출력이 되는 것을 볼 수 있다.
- 화면에 변화가 있다는 것은 builder가 계속 새로 불려온다는 것이다.
- 다시말해 setState()를 사용하지 않고 자동으로 화면에 변화를 줄 수 있다는 것이다.
캐싱
- 코드를 수정해 보았다.
- setState()를 실행시키는 ElevatedButton을 추가했다.
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
'Future Builder',
style: textStyle.copyWith(
fontWeight: FontWeight.w700,
fontSize: 30.0,
),
),
Text(
'ConState : ${snapshot.connectionState}',
style: textStyle,
),
Text(
'Data : ${snapshot.data}',
style: textStyle,
),
Text(
'Error : ${snapshot.error}',
style: textStyle,
),
ElevatedButton(
onPressed: () {
setState(() {});
},
child: Text('setState'),
),
],
);
- 재시작을 하면
ConState 값
이 waiting
에서 done
으로 변경되고 Data 값
도 null
에서 2
로 바뀐다.
- 그런데 버튼을 누르면
ConState
가 waiting
에서 done
으로 바뀌는데 Data 값
은 null
로 바뀌지 않고 기존값 2
에서 4
로 변경이 된다.
- FutureBuilder가 비록 builder를 다시 실행했지만 기존의 데이터 값은 기억을 하는 것이다. 이러한 것을 캐싱이라고 한다.
Stream Builder
import 'dart:math';
import 'package:flutter/material.dart';
class HomeScreen extends StatefulWidget {
const HomeScreen({Key? key}) : super(key: key);
@override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
final textStyle = const TextStyle(
fontSize: 20.0,
);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Padding(
padding: const EdgeInsets.all(8.0),
child: StreamBuilder(
stream: streamNumbers(),
builder: (context, snapshot) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
'Stream Builder',
style: textStyle.copyWith(
fontWeight: FontWeight.w700,
fontSize: 30.0,
),
),
Text(
'ConState : ${snapshot.connectionState}',
style: textStyle,
),
Text(
'Data : ${snapshot.data}',
style: textStyle,
),
Text(
'Error : ${snapshot.error}',
style: textStyle,
),
ElevatedButton(
onPressed: () {
setState(() {});
},
child: Text('setState'),
),
],
);
},
),
),
);
}
Stream<int> streamNumbers() async* {
for (int i = 0; i < 10; i++) {
await Future.delayed(
Duration(seconds: 1),
);
yield i;
}
}
}
- 0부터 8까지 루핑하면서 ConState의 값은 active로 바뀌고 9가 되면서 done으로 바뀐다.
- active는 stream이 끝나지 않은 상태를 말한다.
- Stream Builder도 마찬가지로 기존값은 유지하면서 빌드되는 것을 볼 수 있다.