코드 정리 하는 법
행(Row)별로 할당 된 구역을 나누어서
Column 내 children에
예를 들어 세 구역이라면
_Header()
_Body()
_Footer()로 나누고
1. 각 부분의 세부 코드는 하단으로 뺀다.
2. return 아래로 복붙 해준다.
3. 필요시 인스턴스 추가해준다.(외부에서 받아와야 하는 경우 아래에서는 _Body, _Footer)
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: PRIMARY_COLOR,
body: SafeArea(
child: Padding(
padding: EdgeInsets.symmetric(
horizontal: 16.0,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'랜덤숫자 생성기',
style: TextStyle(
color: Colors.white,
fontSize: 30.0,
fontWeight: FontWeight.w700,
),
),
IconButton(
onPressed: () {},
icon: Icon(
Icons.settings,
color: RED_COLOR,
))
],
),
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children:
randomNumbers
.asMap()
.entries
.map(
(x) => Padding(
padding: EdgeInsets.only(bottom: x.key == 5 ? 0: 16.0),
child: Row(
children: x.value
.toString()
.split('')
.map(
(y) => Image.asset(
'asset/img/$y.png',
height: 70.0,
width: 50.0,
),
)
.toList(),
),
),
)
.toList()
)),
SizedBox(
width: double.infinity,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: RED_COLOR),
onPressed: () {
final rand = Random();
final Set<int> newNumbers = {};
while (newNumbers.length != 6) {
final number = rand.nextInt(45);
newNumbers.add(number);
}
setState(() {
randomNumbers = newNumbers.toList();
}
);
},
child: Text('생성하기')),
)
],
),
),
),
);
}
위에 코드에서
Column아래
children 하위에 있는
Row
Expanded(Column)
SizedBox를
_Header
_Body
_Footer로 나눠보겠다
(네이밍은 사실 상관 없음)
_Header
class _Header extends StatelessWidget {
const ({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const Placeholder();
}
stless 위젯 불러주고
_Header 붙여주고
return 하위에 Row 붙여준다.
class _Header extends StatelessWidget {
const _Header({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'랜덤숫자 생성기',
style: TextStyle(
color: Colors.white,
fontSize: 30.0,
fontWeight: FontWeight.w700,
),
),
IconButton(
onPressed: () {},
icon: Icon(
Icons.settings,
color: RED_COLOR,
))
],
);
}
}
_Body
위 방식으로 코드를 정리하면
class _Body extends StatelessWidget {
const _Body({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children:
randomNumbers //여기서 에러
.asMap()
.entries
.map(
(x) => Padding(
padding: EdgeInsets.only(bottom: x.key == 5 ? 0: 16.0),
child: Row(
children: x.value
.toString()
.split('')
.map(
(y) => Image.asset(
'asset/img/$y.png',
height: 70.0,
width: 50.0,
),
)
.toList(),
),
),
)
.toList()
)
);
}
}
에러가 나는 이유는
생성한 stless위젯에서 randomNumbers를 관리 하지 않기 때문이다
이것을 해결하기 위해서는 외부에서 randomNumbers를 받아와야 한다.
1. 새로 생성한 stless위젯에 randomNumbers를 생성해주고
2. 외부에서 받아와야 하므로 파라미터를 named파라미터를 설정해준다. (required this.randomNumbers)
3. 외부에서 randomNumbers를 보내준다.
class _Body extends StatelessWidget {
final List<int> randomNumbers; //1. 에러난 randomNumbers 생성
const _Body({required this.randomNumbers, Key? key}) : super(key: key);
// 2. 외부에서 받아와야되니까 namedParameter설정
@override
Widget build(BuildContext context) {
return Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: randomNumbers
.asMap()
.entries
.map(
(x) => Padding(
padding: EdgeInsets.only(bottom: x.key == 5 ? 0 : 16.0),
child: Row(
children: x.value
.toString()
.split('')
.map(
(y) => Image.asset(
'asset/img/$y.png',
height: 70.0,
width: 50.0,
),
)
.toList(),
),
),
)
.toList()
));
}
}
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: PRIMARY_COLOR,
body: SafeArea(
child: Padding(
padding: EdgeInsets.symmetric(
horizontal: 16.0,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_Header(),
_Body(), <- 여기에 에러
_Body(randomNumbers: randomNumbers),
3. 외부에서 randomNumbers를 보내줘야 하니까 파라미터로 randomNumbers 설정.
_Footer
class _Footer extends StatelessWidget {
const _Footer({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return SizedBox(
width: double.infinity,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: RED_COLOR),
onPressed: () {
final rand = Random();
final Set<int> newNumbers = {};
while (newNumbers.length != 6) {
final number = rand.nextInt(45);
newNumbers.add(number);
}
setState(() { // <- 이 부분 애러
randomNumbers = newNumbers.toList();
});
},
child: Text('생성하기')),
);
}
}
에러가 나는데 Stless위젯에 setState()는 존재하지 않기 때문에 에러가 난다.(setState()는 statefull위젯)
이럴 때는 onPressed 코드를 상위로 올려줘야 한다.
1. final로 onPressed 설정(final VoidCallBack onPressed)
2. _Footer의 named 파라미터로 onPressed 를 넘겨준다.(const _Footer({required this.onPressed, Key? key}) : super(key: key);
3. 기존에 있던 onPressed 함수를 새로 생성한 OnPressed함수로 대체
4. 위에서 파라미터를 넣어달라고 에러가 나는데 기존에 있던 onPressed 함수를 새로운 이름의 함수로 생성 (onRandomNumberGenerate)
수정한 _Footer Code
class _Footer extends StatelessWidget {
final VoidCallback onPressed; // 1. final로 onPressed 생성
// 2. 외부에서 입력할 named Parameter 설정
const _Footer({required this.onPressed, Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return SizedBox(
width: double.infinity,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: RED_COLOR),
onPressed: onPressed, // 3. 새로 생성한 onPressed로 대체
child: Text('생성하기')),
);
}
}
//4. 기존의 onPressed를 상위에서 재 설정
void onRandomNumberGenerate() {
final rand = Random();
final Set<int> newNumbers = {};
while (newNumbers.length != 6) {
final number = rand.nextInt(45);
newNumbers.add(number);
}
setState(() {
randomNumbers = newNumbers.toList();
});
}
}
제일 처음 코드와 비교해보자
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: PRIMARY_COLOR,
body: SafeArea(
child: Padding(
padding: EdgeInsets.symmetric(
horizontal: 16.0,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [ // 여기가 간단해짐
_Header(),
_Body(randomNumbers: randomNumbers),
_Footer(onPressed: onRandomNumberGenerate,)
],
),
),
),
);
}
원래 있던 코드는 아래와 같이 하단으로 빼준다.
void onRandomNumberGenerate() {
final rand = Random();
final Set<int> newNumbers = {};
while (newNumbers.length != 6) {
final number = rand.nextInt(45);
newNumbers.add(number);
}
setState(() {
randomNumbers = newNumbers.toList();
});
}
}
class _Header extends StatelessWidget {
const _Header({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'랜덤숫자 생성기',
style: TextStyle(
color: Colors.white,
fontSize: 30.0,
fontWeight: FontWeight.w700,
),
),
IconButton(
onPressed: () {},
icon: Icon(
Icons.settings,
color: RED_COLOR,
))
],
);
}
}
class _Body extends StatelessWidget {
final List<int> randomNumbers;
const _Body({required this.randomNumbers, Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: randomNumbers
.asMap()
.entries
.map(
(x) => Padding(
padding: EdgeInsets.only(bottom: x.key == 5 ? 0 : 16.0),
child: Row(
children: x.value
.toString()
.split('')
.map(
(y) => Image.asset(
'asset/img/$y.png',
height: 70.0,
width: 50.0,
),
)
.toList(),
),
),
)
.toList()
));
}
}
class _Footer extends StatelessWidget {
final VoidCallback onPressed;
const _Footer({required this.onPressed, Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return SizedBox(
width: double.infinity,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: RED_COLOR),
onPressed: onPressed,
child: Text('생성하기')),
);
}
}
'Flutter > Flutter 기본' 카테고리의 다른 글
[Flutter] 화면 전환, 데이터 전달1 (navigation) (0) | 2023.05.12 |
---|---|
[Flutter] Button 종류와 설정 (0) | 2023.05.11 |
[Flutter] 중복되는 코드 하나로 줄이기(.map)으로 (0) | 2023.04.21 |
[Flutter]날짜와 시간에 관한 위젯(DateTime/duration,difference) (0) | 2023.04.21 |
[Flutter] state를 상위트리에서 관리하기 (4) | 2023.04.20 |