1. Defining Expenses/Expense Widget Class
간략하게 StatefulWidget를 정의할 class를 만든다. 현재 step에선 부가적인 기능이 들어가기 전이라 Scaffold(앱의 뼈대를 위한 구성요소를 제공하는 Widget)에 임시 Text Widget을 집어넣는다.
import 'package:flutter/material.dart';
class Expenses extends StatefulWidget{
const Expenses({super.key});
@override
State<Expenses>createState(){
return _ExpensesState();
}
}
class _ExpensesState extends State<Expenses>{
@override
Widget build(BuildContext context){
return Scaffold(
body:Column(
children: const [
Text("The car"),
Text("The here"),
],
),
);}
}
2.1 List Initializer
각 데이터가 지니는 특징을 구형할 수 있는 widget class를 만들어야 하는데,이를 Model이라는 폴더를 생성하고 그
아래에 expense.dart라는 파일을 집어넣도록 하자.
아래는 Expense Widget Class의 구성을 담은 내용을 간략하게 적어보았다.
- title (String)
- amount(double)
- date (DateTime)
- id (uuid)
이 때, backend에서도 많이 보았던 고유식별번호인 UUID를 사용하는데, 이를 위해선 flutter에서 module package를 설치해야 한다.
```flutter
flutter pub add uuid
```
더불어서, flutter에는 'initializer list'라는 keyword가 존재하게 된다. 이는, 현재 construcotr에서 받아들이는 외부 parameter외에 이미 class에서 member 변수로서 초기화시킬 때 사용하는 하나의 방법이라 생각하면 된다. 말이 어려우나, 간단히 "constructor에서 오지 않는 매개변수를 내부적으로 class 맴버 변수를 초기화 시키는 하나의 방법이다" 라고 생각하면 됨.
import 'package:uuid/uuid.dart';
// make uuid unresulable
const uuid= Uuid();
class Expense{
//constructor;retrieve arguments
Expense({
required this.title,
required this.amount,
required this.date,
}): id=uuid.v4();
final String id;
final String title;
final double amount;
final DateTime date;
}
2.2 Enumerator
User에게 category를 선택할 수 있도록, 하나의 category를 만들 필요가 있다. 이 때 사용하는 자료구조가 바로 enum이라는 것이다.
enum <Name> {....}
아래의 코드는 Category에 end-user가 선택할 수 있는 목록들을 집어넣으면 되는데, 이때 _주의할 점은 Caetory에 있는 목록들은 쌍따움표나 따움표를 사용하지 않는다는 점_이다.
import 'package:uuid/uuid.dart';
// make uuid unresulable
const uuid= Uuid();
enum Category {food,travel,leisure,work}
class Expense{
//constructor;retrieve arguments
Expense({
required this.title,
required this.amount,
required this.date,
required this.category,
}): id=uuid.v4();
final String id;
final String title;
final double amount;
final DateTime date;
final Category category;
}
3. Add List of Expense to Expenses class
Expenses class에서 memeber변수 하나를 추가하도록 해보자. Expenses Class의 맴버변수의 _registeredExpenses 를 하나 추가하고, 이는 Expense를 원소를 갖는 list로 정하도록 하자. 물론, list안에 있는 Expense의 매개변수는 하드코딩으로 하자.
import 'package:flutter/material.dart';
import 'package:expense_tracker/models/expense.dart';
class Expenses extends StatefulWidget{
const Expenses({super.key});
@override
State<Expenses>createState(){
return _ExpensesState();
}
}
class _ExpensesState extends State<Expenses>{
final List<Expense>_registeredExpenses=[
Expense(
title:"Flutter Course",
amount:12.22,
date:DateTime.now(),
category:Category.work),
Expense(
title:"50-60 Nights",
amount:50,
date:DateTime.now(),
category:Category.leisure),
]
@override
Widget build(BuildContext context){
return Scaffold(
body:Column(
children: const [
Text("The car"),
Text("The here"),
],
),
);
}
}
4. Efiiciently Rendering Long Lists with ListView
User가 소비했던, expense class의 정보들을 모아두고, 이를 화면에 보여주는 것을 생각할 수 있다. 그럼, 첫번째로 우리가 사용할 수 있는 방법은 flutter에서 제공하는 library 'ListView"를 생각할 수 있다. 그러나, 이 ListView에는 치명적인 단점이 존재하는데, List에 속한 원소들의 수가 적은 경우에는 쉽게 사용할 수 있지만, 이게 원소의 숫자가 길어지면 사용하기가 무진장 힘들어진다. 그러므로, 우리는 이를 대체할 수 있는,
ListView.builder를 사용하도록 하자.
이들을 간략하게 구별하는 방법은 아래를 참고하도록 하자!
- 일반적인 ListView를 명시적으로 호출하고 children 전달하는 방법 - 적은 데이터에 사용시 용이함
- ListView.builder builder를 사용하여 동적으로 호출 - 많은 양의 데이터 리스트에 용이함 index사용가능
✍️ListView.builder 아래의 supporting document를 참고하자면, ListView.builder는 - input: Function을 받으며, 매개변수로는 BuildContext 와 int를 받는다. - output: Widget를 return 해야함. |
---|
lib 폴더에 ExpensesList class를 정의한다. build Widget에서 ListView.Builder를 사용하도록 허용하며, Text Widget은 선택된 index에 해당되는 expense을 선정해서, 그에 해당되는 title를 화면에 보여준다.
import 'package:flutter/material.dart';
import 'package:expense_tracker/models/expense.dart';
class ExpensesList extends StatelessWidget{
//initialize constructor
const ExpensesList({super.key,required this.expenses,});
final List<Expense>expenses;
@override
Widget build(BuildContext context){
return ListView.builder(itemCount:expenses.length ,itemBuilder: (ctx,index)=>Text(expenses[index].title),
);
}
}
5. Efiiciently Rendering Long Lists with ListView
위에 정의내린 ExpensesList를 이제 Expense 화면에 집어 넣으려고 하자. 이때, 우리가 할 수 있는 방법은 아래와 같다. Expense class의 children list속에 ExpenseList를 집어넣는 것이다. 아래처럼 말이다.
#expense.dart
import 'package:flutter/material.dart';
import 'package:expense_tracker/models/expense.dart';
import 'package:expense_tracker/expenses_list.dart';
class Expenses extends StatefulWidget{
# 생략
class _ExpensesState extends State<Expenses>{
final List<Expense>_registeredExpenses=[
Expense(
title:"Flutter Course",
amount:12.22,
date:DateTime.now(),
category:Category.work),
Expense(
title:"50-60 Nights",
amount:50,
date:DateTime.now(),
category:Category.leisure),
];
@override
Widget build(BuildContext context){
return Scaffold(
body:Column(
children: [
Text("The chart"),
#List안에 list를 집어넣지만 작동이 안됨.
ExpensesList(expenses:_registeredExpenses)
],
),
);
}
}
그러나, 우리의 기대와는 다르게 화면에는 우리가 ListView에서 지정한 원소들이 나오지를 않는다. 이게 왜 그런것일까? 이유는 Colum안에 ExpenseList를 집어넣었고, 그 List에는 또 column이 존재하기 때문이다. 즉, Column안에 Column이 존재하기 때문이다. 이를 우회하는 방법은 Expanded Widget 을 사용하는 방법이 있다.
class _ExpensesState extends State<Expenses>{
final List<Expense>_registeredExpenses=[
Expense(
title:"Flutter Course",
amount:12.22,
date:DateTime.now(),
category:Category.work),
Expense(
title:"50-60 Nights",
amount:50,
date:DateTime.now(),
category:Category.leisure),
];
@override
Widget build(BuildContext context){
return Scaffold(
body:Column(
children: [
Text("The chart"),
Expanded(child:ExpensesList(expenses:_registeredExpenses)),
],
),
);
}
}
'Front-End > Flutter_Project_02_Expense Tracker' 카테고리의 다른 글
Tracker6. Udemy Flutter 강의를 통한 Project - Expense Tracker (0) | 2024.12.17 |
---|---|
5. Udemy Flutter 강의를 통한 Project - Expense Tracker (0) | 2024.12.13 |
4. Udemy Flutter 강의를 통한 Project - Expense Tracker (0) | 2024.12.10 |
3. Udemy Flutter 강의를 통한 Project - Expense Tracker (0) | 2024.12.07 |
2. Udemy Flutter 강의를 통한 Project - Expense Tracker (0) | 2024.12.05 |