Flutter Riverpod - 파트 2

마지막blog에서는 Flutter 프로젝트를 위해 Riverpod를 설정하는 방법과 모든 Riverpod Provider의 기본인 Provider()를 사용하는 방법을 배웠습니다. 이 블로그에서는 가장 유용하고 기본적인 공급자인 StateProvider()를 사용하는 방법을 배웁니다.

공급자가 필요한 이유를 자세히 살펴보겠습니다.



다음 코드를 포함하는 A Flutter(Riverpod) 프로젝트가 있다고 가정해 보겠습니다.

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

int counter = 0;

void main() {
  runApp(
    const ProviderScope(
      child: MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Riverpod',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Riverpod'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

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

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$counter',
              style: Theme.of(context).textTheme.headline4,
            ),
            const CounterCard()
          ],
        ),
      ),
    );
  }
}

class CounterCard extends StatefulWidget {
  const CounterCard({
    Key? key,
  }) : super(key: key);

  @override
  State<CounterCard> createState() => _CounterCardState();
}

class _CounterCardState extends State<CounterCard> {
  void _incrementCounter() {
    setState(() {
      counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Card(
        child: ListTile(
      title: Text("$counter"),
      trailing: IconButton(
        icon: const Icon(Icons.plus_one),
        onPressed: _incrementCounter,
      ),
    ));
  }
}




이 공급자 범위는 모두 무엇입니까? 귀하의 프로젝트를 위한 Riverpod 설정에 대한 제 previous blog를 읽어보십시오!

그렇다면 위의 코드에서 무슨 일이 벌어지고 있을까요?
새 Flutter 프로젝트를 만들 때 얻는 것과 유사한 기본 Flutter 카운터 응용 프로그램이지만 Riverpod 및 일부 변경 사항을 사용하여 상태 문제를 표시합니다.
0으로 초기화되는 전역 변수int counter가 있습니다. 그런 다음 그 counter는 상위 MyHomePage 클래스와 두 번째 CounterCard 클래스의 두 곳에서 사용됩니다. CounterCard에는 IconButton 변수를 증가시키는 _incrementCounter() 함수가 있는 counter가 있습니다. 이제 이상적으로는 버튼을 누르면 두 위치에서 counter가 증가하는 것을 볼 수 있습니다. 그러나 이것은 일어나지 않습니다. 이는 setState() 메서드가 CounterCard 콘텐츠만 새로 고치고 MyHomePage 콘텐츠는 새로 고치지 않기 때문입니다. Flutter State는 성능을 향상시키기 위해 이러한 방식으로 작동합니다. 작은 변화에 대해 매번 전체 화면이 새로 고쳐지고 M1 장치를 소유하고 있지 않다고 상상해 보십시오. 이 문제를 해결하기 위해 상태 관리 솔루션이 있습니다. 몇 가지 다이어그램을 사용하여 모든 것을 알아 봅시다!! 누가 다이어그램을 좋아하지 않습니까?




따라서 파생 클래스에서 기본 클래스의 상태를 변경하려는 경우(상당히 자주 발생) 상당히 지루해집니다. Riverpod를 사용하여 이 문제를 더 구체적으로 설명하면 상태를 포함하는 Provider 또는 StateProvider()를 사용하여 이 문제를 해결할 것입니다. ) .

그래서 우리는 counter 변수를 가지고 있죠? 우리는 previous blog에서 배운 대로 그것을 Provider로 변환할 것입니다.

//int counter = 0; This Changes to
final counterProvider = Provider<int>((ref) {
  return 0;
});


그리고 마법의 절반은 끝났다!!
MyHomePage를 상태 비저장 위젯으로 변경...

class MyHomePage extends StatelessWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$counter',
              style: Theme.of(context).textTheme.headline4,
            ),
            const CounterCard()
          ],
        ),
      ),
    );
  }
}


previous blog에서 배운 것처럼 MyHomePageConsumerWidget로 다시 변경하고 Text 위젯이 counterProvider()를 보도록 합니다.


class MyHomePage extends ConsumerWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  Widget build(BuildContext context,WidgetRef ref) {
    return Scaffold(
      appBar: AppBar(
        title: Text(title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              ref.watch(counterProvider).toString(),
              style: Theme.of(context).textTheme.headline4,
            ),
            const CounterCard()
          ],
        ),
      ),
    );
  }
}


이제 때로는 StatefulWidget 에서 공급자를 읽어야 하며 ConsumerStatefulWidget StatefulWidget에 대해 수행할 CounterCard를 사용하여 이 작업을 수행합니다.

// Add Consumer to StatefulWidget
class CounterCard extends ConsumerStatefulWidget {
  const CounterCard({
    Key? key,
  }) : super(key: key);

  @override
//    Changes here 
  ConsumerState<CounterCard> createState() => _CounterCardState();
}
//    Changes here 
class _CounterCardState extends ConsumerState<CounterCard> {
 ...
}


그리고 그게 다야!
이제 다른 종류의 제공자에 대해 이야기하기 전에 StateProvider 였던 것을 기억하십시오. 기본적으로는 Provider 이지만 내용의 상태를 유지할 수 있습니다.
이제 위로 이동하여 StatecounterProvider를 추가합니다.

//                                    Over Here
final counterProvider = StateProvider<int>((ref) {
  return 0;
});


이제 CounterCard로 이동하여 TextcounterProvider를 보도록 하십시오.

class _CounterCardState extends ConsumerState<CounterCard> {


  @override
  Widget build(BuildContext context) {
    return Card(
        child: ListTile(
      title: Text(ref.watch(counterProvider).toString()),
      trailing: IconButton(
        icon: const Icon(Icons.plus_one),
        onPressed: (){
          ...
        },
      ),
    ));
  }
}



이제 onPressed에서 counterProvider의 "상태"를 증가시켜야 합니다.
이를 위해 ref.read() 대신 ref.watch 를 사용하므로 여기에 있어야 합니다.

onPressed: () {
          setState(() {
            ref.read(counterProvider.state).state++;
          });
        },


여기서는 setState 함수를 사용하지 않는 경우에도 여전히 작동합니다.
이제 프로그램을 실행하여 이전에 직면한 상태 관리 문제를 해결합니다.

곧 YouTube에서 Riverpod 시리즈를 시작할 예정이니 저와 저를 구독하는 것을 잊지 마시고 Flutter를 사용하여 최신 업데이트와 팁과 요령을 얻으십시오.

좋은 웹페이지 즐겨찾기