![]() |
![]() |
수정 전 | 수정 후 |
- 수정 전의 앱은 각각의 탭에 들어갈 때마다 로딩 스피너가 돌아가면서 API 콜을 해서 데이터를 새로 불러왔다.
- 하지만 교정일기 앱은 사용자가 데이터를 추가하는 경우가 아니라면 업데이트할 필요가 전혀 없다.
- 따라서 불필요한 네트워크 통신을 줄이고, 더 빠른 사용자 경험을 제공하기 위해 최초 1회만 데이터를 불러오고, 그 이후에는 탭을 이동해도 기존에 불러온 데이터를 유지해서 보여주고 싶었다.
위젯의 상태 유지하기 AutomaticKeepAliveClientMixin
- 플러터에서는 기본적으로 탭을 이동하면 보이지 않는 탭의 상태가 `dispose` 되어 메모리에서 제거된다.
- 하지만 ` AutomaticKeepAliveClientMixin`을 사용하면 탭을 이동하더라도 위젯이 보존되며 상태를 유지할 수 있다.
- 이를 통해 불필요한 네트워크 요청이나 위젯 리빌드를 피할 수 있고, 탭을 이동해도 이전 탭의 스크롤 위치를 유지하고 싶은 경우에도 유용하다.
AutomaticKeepAliveClientMixin 적용 코드
class TimelineTab extends StatefulWidget {
const TimelineTab({super.key});
@override
State<TimelineTab> createState() => _TimelineTabState();
}
// ✅ mixin 추가
class _TimelineTabState extends State<TimelineTab> with AutomaticKeepAliveClientMixin {
// ✅ 추가
@override
bool get wantKeepAlive => true;
@override
Widget build(BuildContext context) {
super.build(context); // ✅ 추가
return const Scaffold();
}
}
- `StatefulWidget` 클래스에 `AutomaticKeepAliveClientMixin`를 추가한다.
- `wantKeepAlive`를 `true`로 설정한다.
- `build` 메서드 안에서 `super.build(context)`를 호출한다.
만약 `AutomaticKeepAliveClientMixin`을 추가했는데도 여전히 탭을 이동할 때마다 상태가 초기화된다면 한 가지를 더 수정해야 한다.
BottomNavigaionBar에 PageView 적용하기
- `PageView`와 `AutomaticKeepAliveClientMixin`를 함께 사용하면 현재 보이지 않는 탭도 위젯 트리에서 활성 상태를 유지할 수 있다.
- `PageView`뿐만 아니라 `TabBarView`를 사용할 수도 있다. `TabBarView`를 사용하면 기본적으로 탭을 이동할 때 옆으로 스와이프하는 듯한 애니메이션 효과가 적용된다.
PageView 적용 코드
class _IndexScreenState extends State<IndexScreen> {
late PageController _pageController;
int _currentIndex = 0;
final List<Widget> _tabs = [
const HomeTab(),
const TimelineTab(),
const AlbumTab(),
const ProfileTab(),
];
void _onItemTapped(int index) {
_pageController.jumpToPage(index);
setState(() {
_currentIndex = index;
});
}
@override
void initState() {
super.initState();
_pageController = PageController(initialPage: _currentIndex);
}
@override
void dispose() {
_pageController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: PageView(
physics: const NeverScrollableScrollPhysics(), // 스와이프로 탭 이동 불가
controller: _pageController,
onPageChanged: _onItemTapped,
children: _tabs,
),
bottomNavigationBar: BottomNavigationBar(
type: BottomNavigationBarType.fixed,
currentIndex: _currentIndex,
onTap: _onItemTapped,
items: const [
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: '홈',
),
BottomNavigationBarItem(
icon: Icon(Icons.list),
label: '타임라인',
),
BottomNavigationBarItem(
icon: Icon(Icons.image_outlined),
label: '앨범',
),
BottomNavigationBarItem(
icon: Icon(Icons.person),
label: 'MY',
),
],
),
);
}
}
- `PageController`를 생성하고 `body`에 `PageView`를 적용한다.
이제 탭을 이동해도 해당 탭의 위젯을 다시 빌드하지 않고, 상태도 유지되는 것을 확인할 수 있다.