해당 게시물은 과거에 작성한 블로그 내용을 옮겨 온 것으로, 가독성이 떨어지고 내용이 부정확할 수 있습니다.
- 위젯의 State를 표시하려면 불필요한 위젯들이 ReBuild되는 문제가 발생
- state: 위젯이 빌드되는 동시에 읽을 수 있으며 위젯의 생명 주기 사이에 변경 가능한 정보
- 어플과 사용자 간의 상호작용으로 인하여 변하는 데이터들이 state에 해당
- 해당 문제를 해결하기 위한 게 Provider
- 동일한 데이터를 다른 위젯에게 공유할 때 Provider를 사용하여 전달
- Provider를 사용하면 위젯 트리와 관계없이 state를 저장할 수 있는 클래스 생성
- 해당 state를 공유하는 공통 부모 위젯이 Provider를 제공
- state를 사용할 때는 Provider의 데이터를 가져와서 사용
- 결론적으로 Provider는 state를 관리하기 위한 개념
- Provider
- 생성 파트: 사용할 데이터의 타입과 그 데이터에 대한 Provider를 생성
- 소비 파트: Provider를 사용하여 데이터를 불러오고 수정
- count_provider.dart
// Counter Class 정의
import 'package:flutter/material.dart';
class CountProvider extends ChangeNotifier {
int _count = 0;
int get count => _count;
void increase() { // 숫자를 증가시키는 함수
++_count;
notifyListeners(); // 데이터가 갱신되었음을 알림
}
void decrease() { // 숫자를 감소시키는 함수
--_count;
notifyListeners(); // 선언하지 않을 시 다른 위젯에서 변경된 걸 모름
}
}
- main.dart
// CountProvider 구독
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'provider/count_provider.dart';
import 'screen/home.dart';
void main() {
runApp(App());
}
class App extends StatelessWidget {
const App({Key? key}) : super(key: key);
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: ChangeNotifierProvider( // CountProvidier를 구독
create: (_) => CountProvider(), // CountProvider는 count_provider.dart에 선언
child: Home(), // Home 위젯에서 해당 Provider 사용 가능
),
);
}
}
- home.dart
// CountProvider를 사용하기 위한 home 생성
import 'package:flutter/material.dart';
import 'package:flutter_temp/provider/count_provider.dart';
import 'package:provider/provider.dart';
class Home extends StatelessWidget {
Home({Key? key}) : super(key: key);
late CountProvider _countProvider;
Widget build(BuildContext context) {
// Provider.of -> CountProvider를 호출하고 직접 접근, 상태를 받아와 업데이트 가능
// listen:false -> Home에서는 상태 변경만 하고 위젯을 ReBuild 할 필요가 없음
_countProvider = Provider.of<CountProvider>(context, listen: false);
return Scaffold(
appBar: AppBar(
title: Text('Provider example'),
),
body: CountHome(), // 아래에 선언되어 있음
floatingActionButton: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
IconButton(
onPressed: () => _countProvider.increase(),
icon: Icon(Icons.add), // 아이콘 클릭 시 add()
),
IconButton(
onPressed: () => _countProvider.decrease(),
icon: Icon(Icons.remove), // 아이콘 클릭 시 remove()
),
],
),
);
}
}
class CountHome extends StatelessWidget {
const CountHome({Key? key}) : super(key: key);
Widget build(BuildContext context) {
return Center(
// Consumer로 Provider에 접근한 후 데이터 받아옴
child: Consumer<CountProvider>( // Consumer -> 상태가 변경될 때마다 Build
builder: (context, countProvider, child) => Text(
Provider.of<CountProvider>(context).count.toString(), // count를 화면에 출력
style: TextStyle(fontSize: 60),
),
),
);
}
}