반응형
플러터를 하다보면 하나의 위젯이 덩치가 어마어마하게 커지는 경우가 있다. 이때 setState를 하면 어마어마한 퍼포먼스 문제를 야기한다.
헌데 위젯을 하나하나 따로 빼서 끊어주고 생성자 뚫고 해주는게 여간 쉬운일이 아니다. 이럴 때 사용하는 팁을 적어본다
1. 프로파이더 사용
너무나 당연한 얘기이지만 프로바이더를 사용하면 커다란 빌드 함수 안에서 특정 위젯만 리빌드 할 수 있다.
다만 코드 작성하기가 여간 귀찮다
2. 스트림 컨트롤러와 스트림 빌더 사용
가장 쉬운 방법이다. 특정부분만 리빌드 하고 싶은 부분을 스트림 빌더로 감싸준다.
그리고 스트림컨트롤러르 생성한 뒤 스트림을 스트림빌더에만 내려준다. 즉 특정부분만 setState 하는 효과를 가지게 된다.
3. ChangeNotifier와 ListenableBuilder 조합 사용
https://api.flutter.dev/flutter/widgets/ListenableBuilder-class.html
스트림 컨트롤러만 있는줄 알았는데 다른 방법도 있다. 구글도 역시 이런거 다 만들어 놓았네..
import 'package:flutter/material.dart';
/// Flutter code sample for a [ChangeNotifier] with a [ListenableBuilder].
void main() {
runApp(const ListenableBuilderExample());
}
class CounterModel with ChangeNotifier {
int _count = 0;
int get count => _count;
void increment() {
_count += 1;
notifyListeners();
}
}
class ListenableBuilderExample extends StatefulWidget {
const ListenableBuilderExample({super.key});
@override
State<ListenableBuilderExample> createState() =>
_ListenableBuilderExampleState();
}
class _ListenableBuilderExampleState extends State<ListenableBuilderExample> {
final CounterModel _counter = CounterModel();
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('ListenableBuilder Example')),
body: CounterBody(counterNotifier: _counter),
floatingActionButton: FloatingActionButton(
onPressed: _counter.increment,
child: const Icon(Icons.add),
),
),
);
}
}
class CounterBody extends StatelessWidget {
const CounterBody({super.key, required this.counterNotifier});
final CounterModel counterNotifier;
@override
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text('Current counter value:'),
// Thanks to the ListenableBuilder, only the widget displaying the
// current count is rebuilt when counterValueNotifier notifies its
// listeners. The Text widget above and CounterBody itself aren't
// rebuilt.
ListenableBuilder(
listenable: counterNotifier,
builder: (BuildContext context, Widget? child) {
return Text('${counterNotifier.count}');
},
),
],
),
);
}
}
4. ValueNotifier와 ValueListenableBuilder 조합 사용
https://medium.com/@thekavak/flutter-valuenotifier-with-examples-66b3933d7036
위와 비슷한 기능. 단 단일 밸류에만 유용함
ChangeNotifier 공식문서에서도 사용하는 예제가 있음
import 'package:flutter/material.dart';
/// Flutter code sample for a [ValueNotifier] with a [ListenableBuilder].
void main() {
runApp(const ListenableBuilderExample());
}
class ListenableBuilderExample extends StatefulWidget {
const ListenableBuilderExample({super.key});
@override
State<ListenableBuilderExample> createState() =>
_ListenableBuilderExampleState();
}
class _ListenableBuilderExampleState extends State<ListenableBuilderExample> {
final ValueNotifier<int> _counter = ValueNotifier<int>(0);
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('ListenableBuilder Example')),
body: CounterBody(counterValueNotifier: _counter),
floatingActionButton: FloatingActionButton(
onPressed: () => _counter.value++,
child: const Icon(Icons.add),
),
),
);
}
}
class CounterBody extends StatelessWidget {
const CounterBody({super.key, required this.counterValueNotifier});
final ValueNotifier<int> counterValueNotifier;
@override
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text('Current counter value:'),
// Thanks to the ListenableBuilder, only the widget displaying the
// current count is rebuilt when counterValueNotifier notifies its
// listeners. The Text widget above and CounterBody itself aren't
// rebuilt.
ListenableBuilder(
listenable: counterValueNotifier,
builder: (BuildContext context, Widget? child) {
return Text('${counterValueNotifier.value}');
},
),
],
),
);
}
}
반응형
'Flutter' 카테고리의 다른 글
freezed 왜씀? dart data class를 사용하자! (0) | 2024.04.16 |
---|---|
CustomPainter를 redraw 하는 방법 (0) | 2024.03.15 |
iOS에서 상하단에 색이 생길 때 해결방법 (0) | 2024.02.03 |
PageRouteBuilder에서 iOS backSwipe가 안될 때 (0) | 2024.02.03 |
Bottom에서 Pull to refresh하기 (0) | 2024.01.31 |
댓글