반응형

Provider 패턴은 Flutter 애플리케이션에서 상태 관리를 효율적으로 수행하기 위해 사용되는 패턴입니다. 이 패턴은 InheritedWidget을 기반으로 하며, 상태를 위젯 트리에서 쉽게 공유하고 관리할 수 있게 도와줍니다. Provider 패턴은 Flutter의 공식 상태 관리 솔루션 중 하나로, 단순하고 강력한 상태 관리 방법을 제공합니다.

 

주요 개념

 

1. Provider:

상태를 제공하는 역할을 합니다. Provider는 다양한 유형이 있으며, ChangeNotifierProvider, Provider, FutureProvider, StreamProvider 등이 있습니다.

2. ChangeNotifier:

상태 변경을 알리기 위해 사용되는 클래스입니다. ChangeNotifier를 상속받아 상태를 관리하고, notifyListeners()를 호출하여 리스너들에게 상태 변경을 알립니다.

3. Consumer:

Provider에서 제공하는 상태를 구독하고, 상태가 변경될 때마다 UI를 업데이트하는 역할을 합니다.

 

Provider의 유형

 

1. ChangeNotifierProvider:

ChangeNotifier를 사용하여 상태를 제공하고 관리합니다.

2. Provider:

기본적인 상태 제공자로, 변경되지 않는 데이터를 제공할 때 사용합니다.

3. FutureProvider:

비동기 작업의 결과를 제공하는 Provider입니다.

4. StreamProvider:

스트림 데이터를 제공하는 Provider입니다.

 

예제: ChangeNotifierProvider 사용

 

간단한 카운터 애플리케이션을 Provider 패턴으로 구현한 예제를 살펴보겠습니다.


dependencies 에 추가

provider:

 

모델 클래스

import 'package:flutter/foundation.dart';

class Counter with ChangeNotifier {
  int _count = 0;

  int get count => _count;

  void increment() {
    _count++;
    notifyListeners();
  }

  void decrement() {
    _count--;
    notifyListeners();
  }
}

메인 애플리케이션

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'counter.dart'; // Counter 모델 클래스 가져오기

void main() {
  runApp(
    MultiProvider(
      providers: [
        ChangeNotifierProvider(create: (_) => Counter()),
      ],
      child: MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: CounterPage(),
    );
  }
}

class CounterPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final counter = Provider.of<Counter>(context);

    return Scaffold(
      appBar: AppBar(
        title: Text('Provider Counter Example'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'Counter: ${counter.count}',
              style: TextStyle(fontSize: 24),
            ),
          ],
        ),
      ),
      floatingActionButton: Column(
        mainAxisAlignment: MainAxisAlignment.end,
        children: [
          FloatingActionButton(
            onPressed: counter.increment,
            child: Icon(Icons.add),
          ),
          SizedBox(height: 10),
          FloatingActionButton(
            onPressed: counter.decrement,
            child: Icon(Icons.remove),
          ),
        ],
      ),
    );
  }
}

주요 구성 요소

 

1. Counter 모델 클래스:

ChangeNotifier를 상속받아 상태를 관리합니다.

incrementdecrement 메서드를 통해 상태를 변경하고, notifyListeners()를 호출하여 리스너에게 상태 변경을 알립니다.

2. MultiProvider:

여러 Provider를 동시에 제공할 때 사용합니다. 이 예제에서는 ChangeNotifierProvider를 사용하여 Counter 상태를 제공합니다.

3. Provider.of(context):

현재 컨텍스트에서 Provider가 제공하는 상태를 구독합니다. 여기서는 Counter 상태를 구독하여 카운터 값을 업데이트합니다.

4. FloatingActionButton:

onPressed 콜백에서 counter.incrementcounter.decrement를 호출하여 카운터 값을 증가 및 감소시킵니다.

 

 

 

다른 예시(실습)

필요 파일
provider 패키지
- album_provider.dart
model 패키지
- album.dart

view 패키지

- album_provider_view.dart

 

album.dart

class Album {
  int? userId;
  int? id;
  String? title;

  Album({this.userId, this.id, this.title});

  factory Album.fromJson(Map<String, dynamic> json) {
    return Album(
      userId: json['userId'],
      id: json['id'],
      title: json['title'],
    );
  }
}

 

album_provider.dart

import 'dart:convert';

import 'package:flutter/cupertino.dart';
import 'package:http/http.dart' as http;

import '../model/album.dart';

class AlbumProvider with ChangeNotifier {
  final List<Album> _albumList = List.empty(growable: true);

  List<Album> getAlbumList() {
    _fetchAlbums();
    return _albumList;
  }

  void _fetchAlbums() async {
    final response = await http.get(Uri.parse("https://jsonplaceholder.typicode.com/albums"));
    final List<Album> result = jsonDecode(response.body)
        .map<Album>((json) => Album.fromJson(json))
        .toList();
    _albumList.clear();
    _albumList.addAll(result);
    notifyListeners();
  }
}

album_provider_view.dart

import 'package:flutter/material.dart';
import 'package:flutter_lecture/provider/album_provider.dart';
import 'package:provider/provider.dart';

import '../model/album.dart';

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

  late List<Album> albumList;

  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider<AlbumProvider>(
      create: ((context) => AlbumProvider()),
      child: Scaffold(
        appBar: AppBar(
          title: const Text("test title"),
        ),
        body: Consumer<AlbumProvider>(
          builder: (context, provider, child) {
            albumList = provider.getAlbumList();
            return ListView.builder(
                itemCount: albumList.length,
                itemBuilder: (context, index) {
                  return Container(
                    padding: const EdgeInsets.all(10),
                    child: Text("${albumList[index].id} : ${albumList[index].title}"),
                  );
                }
            );
          },
        ),
      ),
    );
  }
}

 

 

 

Provider 패턴의 장점

 

1. 단순성:

Provider 패턴은 Flutter의 상태 관리 솔루션 중 가장 단순하면서도 강력한 패턴입니다.

2. 유연성:

다양한 유형의 Provider를 제공하여 다양한 상태 관리 요구를 충족할 수 있습니다.

3. 성능 최적화:

Provider는 효율적으로 상태를 구독하고 업데이트하여 성능을 최적화합니다.

4. 재사용성:

상태와 비즈니스 로직을 별도의 클래스로 분리하여 재사용성을 높입니다.

 

참고 문서

 

Provider 패키지 문서

Flutter 공식 상태 관리 문서

 

이 정보를 통해 Flutter 애플리케이션에서 Provider 패턴을 효과적으로 사용하여 상태 관리를 수행할 수 있습니다. Provider 패턴을 활용하면 코드의 구조를 개선하고 유지보수성을 높일 수 있습니다.

반응형

'프론트엔드 > Flutter' 카테고리의 다른 글

flutter local notifications - 알림  (0) 2024.07.22
flutter get_it 패턴  (1) 2024.07.22
flutter bloc 패턴 적용  (0) 2024.07.22
flutter 리프레쉬 인디케이터  (0) 2024.07.22
dart 반복문 정리  (0) 2024.07.21

+ Recent posts