728x90
반응형
3단계 작업 (InheritedWidget 사용 해보기)
앞의 단계를 보고싶다면 아래의 링크로
props Drilling을 해결하기 위한 방안
Inherited_Parent
// InheritedWidget 내장 데이터 타입을 상속받아 구현한다.
import 'package:flutter/cupertino.dart';
import '../common.utils/logger.dart';
class InheritedParent extends InheritedWidget {
// 공유 상태 데이터 관리에 목적
// List<String> mySelectedBooks = [];
List<String> state; // 카드에 담긴 책 목록(공유 상태)
// 부모에게 콜백 메서드를 관리하는 목적
void Function(String book) onPressed; // 이벤트 핸들러
// HOW <-- 사용방법
// WHY <---
InheritedParent({
required this.state,
required this.onPressed,
required super.child,
});
// 상태가 변경되었는지 여부를 판단하는 메서드
// 주의점 ! InheritedWidget --> 재정의 클래스를 InheritedParent 넣어 주자.
// 메서드안 InheritedParent 타입 확인
@override
bool updateShouldNotify(covariant InheritedParent oldWidget) {
logger.d('InheritedParent - updateShouldNotify() 호출 확인 ');
// 상태가 달라졌다면 어떻게 판별할까?
if (state.length != oldWidget.state.length) {
logger.d('상태 변경 됨 ');
return true;
}
for (int i = 0; i < state.length; i++) {
// state --> String --> '호모사피엔스'
// state[i] --> String ---> 호모사피엔스
if (state[i] != oldWidget.state[i]) {
return true;
}
}
// 상태 변경이 없으면 false 를 반환하여 자식 위젯을 다시 빌드 않되도록 한다.
return false; // 상태 변경 없음
}
}
home_screen
import 'package:flutter/material.dart';
import 'package:flutter_statement/_03/inherited_parent.dart';
import '../common.utils/logger.dart';
import 'book_cart_page.dart';
import 'book_list_page.dart';
class HomeScreen extends StatefulWidget {
HomeScreen({super.key});
@override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
//로컬상태
int pageIndex = 0;
// 공유상태 => 여러 위젯에서 관리할 수 있음 => 카트에 담긴 책 정보( 책 리스트 화면과, 장바구니 화면에서 공유하는 데이터)
// 상품 -> 책 (String) 타입으로 관리하자
//객체 배열로 관리할 수 있다.
List<String> mySelectedBook = [];
//상태를 변경하는 메서드 만들기
void _toggleSaveStates(String book) {
//다시 화면을 그려라 => 요청함수
setState(() {
if (mySelectedBook.contains(book)) {
mySelectedBook.remove(book);
} else {
mySelectedBook.add(book);
}
});
}
@override
void initState() {
// TODO: implement initState
super.initState();
setState(() {
pageIndex = 0;
});
}
void _changePageIndex(int index) {
setState(() {
pageIndex = index;
});
}
@override
Widget build(BuildContext context) {
logger.d('HomeScreen build 메서드 호출됨 ');
return SafeArea(
child: Scaffold(
appBar: AppBar(
leading: IconButton(
onPressed: () {
_changePageIndex(0);
},
icon: Icon(
Icons.arrow_back_ios,
color: Colors.white,
),
),
title: Text(
'지니의 서재',
style: TextStyle(color: Colors.white),
),
actions: [
IconButton(
onPressed: () {
_changePageIndex(1);
},
icon: Icon(Icons.shopping_cart),
color: Colors.white,
)
],
backgroundColor: Theme.of(context).colorScheme.onSurfaceVariant,
),
body: InheritedParent(
state: mySelectedBook,
onPressed: _toggleSaveStates,
//super.child
child: IndexedStack(
index: pageIndex,
children: [
BookListPage(),
BookCartPage(),
],
),
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: pageIndex,
onTap: (index) {
return _changePageIndex(index);
},
items: [
BottomNavigationBarItem(icon: Icon(Icons.list), label: 'book-list'),
BottomNavigationBarItem(
icon: Icon(Icons.shopping_cart), label: 'book-cart'),
],
),
));
}
}
book_list_page
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import '../common.utils/logger.dart';
import 'inherited_parent.dart';
class BookListPage extends StatelessWidget {
BookListPage({super.key});
//임시데이터 - 교보문고에 볼 수 있는 책 목록 리스트
final List<String> books = [
'호모사피엔스',
'dart입문',
'홍길동전',
'code Refactoring',
'전치사도감',
];
@override
Widget build(BuildContext context) {
//buildcontext를 사용하여 inheritedParentWidget에 접근할 수 있음
InheritedParent? inheritedParent =
context.dependOnInheritedWidgetOfExactType();
List<String> mySelectedBooked = inheritedParent?.state ?? [];
logger.d('데이터 확인 : ${inheritedParent?.state.toString()}');
return inheritedParent == null
? const Center(
child: Text('데이터가 없습니다.'),
)
: SafeArea(
child: Scaffold(
body: ListView(
children: books.map(
(book) {
//함수의 body에는 식을 작성할 수 있다
final isSelecedBook = mySelectedBooked!.contains(book);
//부모가 관리하는 장바구니 데이터에 있는지 없는지
return ListTile(
leading: Container(
width: 35,
height: 35,
decoration: BoxDecoration(
color: Theme.of(context).secondaryHeaderColor,
borderRadius: BorderRadius.circular(8.0),
border:
Border.all(color: Theme.of(context).primaryColor),
),
),
title: Text(
book,
style: TextStyle(
fontSize: 12, fontWeight: FontWeight.bold),
),
trailing: IconButton(
onPressed: () {
inheritedParent.onPressed(book);
},
icon: isSelecedBook
? Icon(Icons.remove_circle)
: Icon(Icons.add_circle),
color: isSelecedBook ? Colors.red : Colors.green,
),
);
},
).toList(),
),
),
);
}
}
book_cart_page
import 'package:flutter/material.dart';
import 'package:flutter_statement/_03/inherited_parent.dart';
class BookCartPage extends StatelessWidget {
const BookCartPage({super.key});
@override
Widget build(BuildContext context) {
InheritedParent inheritedParent = context
.dependOnInheritedWidgetOfExactType<InheritedParent>()!; //null assert
List<String> mySelectedBooked = inheritedParent.state;
return ListView(
children: mySelectedBooked.map((cart) {
return ListTile(
leading: Container(
width: 35,
height: 35,
decoration: BoxDecoration(
color: Theme.of(context).secondaryHeaderColor,
borderRadius: BorderRadius.circular(8.0),
border: Border.all(color: Theme.of(context).primaryColor),
),
),
title: Text(
cart,
style: TextStyle(fontSize: 12, fontWeight: FontWeight.bold),
),
trailing: IconButton(
onPressed: () {
inheritedParent.onPressed(cart);
},
icon: Icon(
Icons.remove_circle,
color: Theme.of(context).primaryColor,
)),
);
}).toList());
}
}
inheritedWidget의 단점이자 사용하지 않는 이유
=> 상위에 위치해있는 경우 상태가 변할 때 하위의 모든 build가 rebuild되어진다.
그렇기 때문에 너무 큰 단점이기 때문에, 상태관리 provider, riverpod등의 상태관리 라이브러리를 사용하게 된다.
728x90
반응형
'Flutter' 카테고리의 다른 글
[Flutter] 상태관리가 되는 앱 만들어 보기 03 (RiverPod) (1) | 2025.01.21 |
---|---|
[flutter] 상태관리가 되는 앱 만들어 보기 01 (1) | 2025.01.20 |
[flutter] 로컬 상태와 공유 상태 (0) | 2025.01.20 |
댓글