Flutter/pakages

[Flutter] Provider์— ๋Œ€ํ•ด์„œ ์‚ฌ์šฉ๋ฒ•์— ๋Œ€ํ•ด ์‹ค์ œ ์˜ˆ์ œ์ฝ”๋“œ๋กœ ์•Œ์•„๋ณด์ž

Hac. Dog ๐ŸŒญ 2024. 4. 21. 16:00

 

1. ๋“ค์–ด๊ฐ€๊ธฐ์— ์•ž์„œ

Provider๋ž€ InheritedWidget์„ ๋ณด๋‹ค ์‰ฝ๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ฃผ๋Š” ์ƒํƒœ๊ด€๋ฆฌ ํŒจํ‚ค์ง€์ž…๋‹ˆ๋‹ค.

1. ์ž‘์„ฑํ•ด์•ผ ํ•˜๋Š” ์ฝ”๋“œ ๊ฐ์†Œ

2. ์›ํ•˜๋Š” ์œ„์ ฏ๋งŒ ์„ ํƒ์ ์œผ๋กœ ๊ฐฑ์‹  ๊ฐ€๋Šฅ

3. Lazy loading ์ง€์›

4. ์ƒํƒœ๋ฅผ ๋ณ„๋„ ํด๋ž˜์Šค๋กœ ๋ถ„๋ฆฌํ•˜๋ฏ€๋กœ StatefulWidget ๋ณด๋‹ค ์œ ์ง€ ๊ด€๋ฆฌ ์šฉ์ด

- ๋‹จ์ 

1. Provider๊ฐ€ ๋ถ€๋ชจ ์œ„์ ฏ์œผ๋กœ ๋“ฑ๋ก๋˜์–ด ์žˆ์ง€ ์•Š์€ ๊ฒฝ์šฐ, ์ž์‹ ์œ„์ ฏ์—์„œ ์ ‘๊ทผ์‹œ ๋Ÿฐํƒ€์ž„ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒ

2. ์œ„์ ฏ ํŠธ๋ฆฌ์ƒ์— ๋“ฑ๋ก์‹œ ์˜์กด์„ฑ ์ˆœ์„œ ์ค‘์š”

 


2.  Provider ์‚ฌ์šฉํ•ด๋ณด๊ธฐ

 

2-1. Provider ์‚ฌ์šฉ๋ฒ• ๊ฐ„๋žต ์„ค๋ช…

Provider๋Š” ChangeNotifier๋ฅผ ์ƒ์†๋ฐ›์•„์„œ, ๋ณ€๊ฒฝ์‚ฌํ•ญ์ด ์žˆ๋Š” ๊ฒฝ์šฐ์— notifyListener()๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์ž์‹ ์œ„์ ฏ๋“ค์„ ๊ฐฑ์‹  ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ’ก DartPad์—์„œ Provider๋ฅผ ์ด์šฉํ•œ ์ƒํƒœ ๊ด€๋ฆฌ ์˜ˆ์‹œ
https://dartpad.dev/?id=d7b22cc9ba4dfa4bd71b2583a94e31b4

 

ChangeNotifierProvider(
  create: (context) => FirstProvider(),
  child: const MaterialApp(
    home: HomeScreen(),
  ),
);

InheritedWidget์„ ๋ถ€๋ชจ ์œ„์ ฏ์œผ๋กœ ์ถ”๊ฐ€ํ–ˆ๋˜ ๊ฒƒ๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ, Provider๋„ ์œ„์ ฏ ํŠธ๋ฆฌ์— ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ถ”๊ฐ€ํ•ด์•ผ ์ž์‹ ์œ„์ ฏ๋“ค์ด ์ ‘๊ทผ์„ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋„์™€์ค๋‹ˆ๋‹ค.

Widget build(BuildContext context) {
    print('reBuild');
    FirstProvider provider = context.watch<FirstProvider>();

    return Scaffold(
      body: Center(
        child: Text('${provider.counter}'),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () => provider.increment(),
        child: const Icon(Icons.plus_one),
      ),
    );
  }

์ž์‹์œ„์ ฏ์—์„œ๋Š” context.watch()๋กœ Provider์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์–ด์„œ ๋งŒ์•ฝ listenํ•˜๊ณ  ์žˆ๋Š” ๊ฐ’๋“ค์˜ ๋ณ€๋™์‚ฌํ•ญ์ด ์ƒ๊ธด๋‹ค๋ฉด

notifyListener()๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  ์ƒˆ๋กญ๊ฒŒ Build()ํ•จ์ˆ˜๊ฐ€ ํ™”๋ฉด์„ ์ƒˆ๋กญ๊ฒŒ ๊ฐฑ์‹ ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

๐Ÿ’ก context.watch()๋Š” ProviderํŒจํ‚ค์ง€์—์„œ extension์œผ๋กœ Buildcontext๋ฅผ ํ™•์žฅํ•˜์—ฌ ๊ตฌํ˜„ํ•œ ํ•จ์ˆ˜ ์ž…๋‹ˆ๋‹ค.

 


2-2. ๊ฐ’ ์ฝ๊ธฐ

๊ฐ’์„ ์ฝ๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ๋Š” ๊ณต์‹๋ฌธ์„œ์—์„œ๋Š” 3๊ฐ€์ง€ ๋ฐฉ๋ฒ•์„ ์„ค๋ช…ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

1. context.watch<T>() : ์œ„์ ฏ์ด T์˜ ๋ณ€ํ™”๋ฅผ ๊ฐ์ง€ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.
== Provider.of<T>(context, listen : true)

2. context.read<T>() : T๋ฅผ ๋ณ€ํ™” ๊ฐ์ง€ ์—†์ด return ํ•ฉ๋‹ˆ๋‹ค.
== Provider.of(context, listen : false)

3. context.select<T, R> : T์˜ ์ผ๋ถ€ ์ž‘์€ ์˜์—ญ์— ๋Œ€ํ•ด์„œ๋งŒ ์œ„์ ฏ์ด ๋ณ€ํ™”๋ฅผ ๊ฐ์ง€ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

๊ฐ„๋‹จํ•˜๊ฒŒ ์ƒํƒœ๊ฐ€ ๋ณ€ํ™”๋˜์„œ ์žฌ๋นŒ๋“œ๋ฅผ ํ•˜๊ณ  ์‹ถ์„๋•Œ๋Š” watch๋ฅผ ์•„๋‹๊ฒฝ์šฐ๋Š” read๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

์ด ๋ง์€ ์ฆ‰, read๋Š” ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜์—ˆ์„ ๋•Œ ์œ„์ ฏ์„ ์žฌ๋นŒ๋“œ ํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ stf widget์—์„œ๋Š” ์‚ฌ์šฉํ•  ์ˆ˜๊ฐ€ ์—†๋‹ค๋Š” ์˜๋ฏธ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

 


2-3. Provider์˜ ์„ ํƒ์  ์˜์กด ๋ฐ ๋‹ค์ค‘ Provider

context.watch<Model>()

์œ„ ์ฝ”๋“œ์—์„œ ๋งŒ์•ฝ Model์ด๋ผ๋Š” Provider๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด
ProviderNotFoundException ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ ๋งค์นญ๋˜๋Š” provider๋ฅผ ์ฐพ์ง€ ๋ชปํ–ˆ์„ ๊ฒฝ์šฐ์—๋Š” null๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋„๋ก ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š”

context.watch<Model?>()

์œ„ ์ฒ˜๋Ÿผ ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

๋‹ค๋งŒ provider๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ๋ฅผ ์ง€์›ํ•˜๋Š” ์ผ€์ด์Šค๊ฐ€ ๋ญ๊ฐ€ ์žˆ๋Š”์ง€ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค...

(provider๊ฐ€ ์กด์žฌํ•˜๋‹ˆ๊น read/watch๋ฅผ ์‚ฌ์šฉํ•˜๋Š”๊ฑด๋ฐ... null๊ฐ’์ด ์žˆ์„๋ฆฌ๊ฐ€..์žˆ๋‚˜?)

์žˆ์œผ๋‹ˆ๊น ์ง€์›ํ•˜๊ฒ ์ฃ ..?

 

๋‘๋ฒˆ์งธ๋กœ๋Š” MultiProvider์ž…๋‹ˆ๋‹ค.

์ง€๊ธˆ๊นŒ์ง€ ๋ฐฐ์šด ๋‚ด์šฉ์œผ๋กœ๋Š” ๋งŒ์•ฝ ๋“ฑ๋กํ•˜๋ ค๋Š” Provider๊ฐ€ 2๊ฐœ ์ด์ƒ์ผ ๊ฒฝ์šฐ๋Š”

Provider<Something>(
  create: (_) => Something(),
  child: Provider<SomethingElse>(
    create: (_) => SomethingElse(),
    child: Provider<AnotherThing>(
      create: (_) => AnotherThing(),
      child: someWidget,
    ),
  ),
),

์ด๋ ‡๊ฒŒ ์ž‘์„ฑํ•ด์•ผ ํ• ํ…๋ฐ ๊ฐ€๋…์„ฑ์ด ๋งค์šฐ ์ข‹์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ด๋ฅผ ์•„๋ž˜์™€ ๊ฐ™์ด ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

MultiProvider(
  providers: [
    Provider<Something>(create: (_) => Something()),
    Provider<SomethingElse>(create: (_) => SomethingElse()),
    Provider<AnotherThing>(create: (_) => AnotherThing()),
  ],
  child: someWidget,
)

์œ„ ๋‘ ์ฝ”๋“œ๋Š” ์™„์ „ํžˆ ๋™์ผํ•˜๊ฒŒ ์ž‘๋™ํ•˜๊ณ , MultiProvider๋Š” ๋‹จ์ˆœํžˆ ์ฝ”๋“œ์˜ ์™ธ๊ด€์„ ๋ฐ”๊ฟ”์ค„ ๋ฟ์ž…๋‹ˆ๋‹ค.

 


2-4. ProxyProvider๋ž€?

ProxyProvider๋ž€ 3.0.0 ๋ฒ„์ „๋ถ€ํ„ฐ ์ƒˆ๋กญ๊ฒŒ ์ถ”๊ฐ€๋œ ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค.

๋‹ค๋ฅธ provider๋“ค์˜ ์—ฌ๋Ÿฌ ๊ฐ’์„ ํ•˜๋‚˜์˜ ๊ฐ์ฒด๋กœ ๋ฌถ์–ด Provider๋กœ ์ „๋‹ฌํ•˜๋Š” provider ์ž…๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋ฉด ํ•ด๋‹น ์‹ ๊ทœ ๊ฐ์ฒด๋Š” ์šฐ๋ฆฌ๊ฐ€ ์˜์กดํ•˜๋Š” provider ์ค‘ ํ•˜๋‚˜๊ฐ€ ์—…๋ฐ์ดํŠธ ๋ ๋•Œ๋งˆ๋‹ค ์—…๋ฐ์ดํŠธ ๋ฉ๋‹ˆ๋‹ค.

 

๊ณต์‹๋ฌธ์„œ๋ฅผ ์ฝ์œผ๋ฉด์„œ ์ด๊ฑธ ๋„๋Œ€์ฒด ์–ธ์ œ ์“ฐ๋Š”๊ฑฐ์ง€..? ๋ผ๋Š” ์ƒ๊ฐ์ด ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค.

์•„๋ž˜ ์˜ˆ์‹œ์™€ ํ•จ๊ป˜ ์–ด๋–จ๋•Œ ์‚ฌ์šฉํ•˜๋ฉด ์ข‹์€์ง€ ๋ณด๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

int count;

Provider(
  create: (_) => MyModel(count),
  child: ...
)

์œ„์™€ ๊ฐ™์ด Provider์—  ๋ณ€๊ฒฝ๋  ์ˆ˜ ์žˆ๋Š” ๋ณ€์ˆ˜๋กœ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ด…์‹œ๋‹ค.

์ด๋ ‡๊ฒŒ ์ƒ์„ฑ์„ ํ–ˆ๋‹ค๊ณ  ํ•œ๋‹ค๋ฉด, ์ƒ์„ฑ๋œ ๊ฐ์ฒด๋Š” ๊ฐ’์ด ๋ณ€ํ™”ํ•ด๋„ ์—…๋ฐ์ดํŠธ๊ฐ€ ๋˜์ง€ ์•Š์„ ๊ฒƒ ์ž…๋‹ˆ๋‹ค.

๋˜ํ•œ, ์‹ค์ œ๋กœ ๊ณต์‹๋ฌธ์„œ์—๋„ ์ด๋ ‡๊ฒŒ ์‚ฌ์šฉํ•˜์ง€ ๋ง๋ผ๊ณ  ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.

int count;

ProxyProvider0(
  update: (_, __) => MyModel(count),
  child: ...
)

์ด๋ ‡๊ฒŒ ProxyProvider๋ฅผ ํ†ตํ•ด์„œ ์‹œ๊ฐ„์— ๋”ฐ๋ผ ๋ณ€๊ฒฝ๋  ์ˆ˜ ์žˆ๋Š” ๋ณ€์ˆ˜๋กœ๋ฅผ ๊ฐ์ฒด์— ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์„œ ProxyProvider์— ์žˆ๋Š” ์ˆซ์ž๋Š” ProxyProvider๊ฐ€ ์˜์กดํ•˜๋Š” ๋‹ค๋ฅธ ๊ณต๊ธ‰์ž์˜ ์ˆ˜ ์ž…๋‹ˆ๋‹ค.

 

https://dartpad.dev/?id=71e1f23bf7076de716bcb30811a7eb8d

์ž์„ธํ•œ ๋‚ด์šฉ์€ ์œ„ ๋งํฌ๋ฅผ ์ฐธ๊ณ ํ•ด์ฃผ์„ธ์š”

1์ดˆ๋งˆ๋‹ค ๋ณ€๊ฒฝ๋˜๋Š” ํ˜„์žฌ ์‹œ๊ฐ„์˜ ๊ฐ’์˜ ๋ณ€์ˆ˜๋ฅผ ProxyProvider์— ์ „๋‹ฌํ•˜์—ฌ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“  ์˜ˆ์ œ์ž…๋‹ˆ๋‹ค.

 


2-5. Consumer

consumer๋ž€ watch์™€ ๋™์ผํ•˜๋‚˜, ํŠน์ • ์œ„์ ฏ๋งŒ ๊ฐฑ์‹ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ธฐ๋ณธ์ ์œผ๋กœ๋Š” ์ƒํƒœ๊ฐ€ ๋ณ€ํ•˜๊ฒŒ ๋˜๋ฉด Build()ํ•จ์ˆ˜๋ถ€ํ„ฐ ์žฌ๋นŒ๋“œ๊ฐ€ ์‹œ์ž‘๋˜๋Š”๋ฐ

Cosumer๋กœ ์œ„์ ฏ์„ ๊ฐ์‹ธ๋ฉด ์ƒํƒœ๊ฐ€ ๋ณ€๊ฒฝ๋˜๋ฉด ๊ทธ ์•ˆ์—์„œ๋งŒ ์ƒํƒœ๊ฐ€ ๋ณ€๊ฒฝ๋˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

https://dartpad.dev/?id=c9d05cc219059a84e3d832c49c84a87e

'MyApp build() ์‹คํ–‰ ๋จ' ์ด๋ผ๋Š” ํ…์ŠคํŠธ๋Š” ํ•œ๋ฒˆ๋งŒ ์ถœ๋ ฅ์ด ๋˜๊ณ 

counter์˜ ๊ฐ’์ด ์ฆ๊ฐ€ํ•ด๋„ Cosumer ์•ˆ์—์„œ๋งŒ ์ƒํƒœ๊ฐ€ ๋ณ€ํ•˜๊ธฐ ๋•Œ๋ฌธ์—

'MyApp build() ์‹คํ–‰ ๋จ'์€ ๋”์ด์ƒ ์‹คํ–‰๋˜์ง€ ์•Š๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 


2-6. Selector

select์™€ ๋™์ผํ•˜๋‚˜, ํŠน์ • ์œ„์ ฏ๋งŒ ๊ฐฑ์‹  ํ•ฉ๋‹ˆ๋‹ค.

https://dartpad.dev/?id=070c0a54bec23b5bc158791db90ba0c2

 

DartPad

 

dartpad.dev

 


3. Provider ์ œ๊ณต์ž

๋งŒ์•ฝ ๋ณ€๊ฒฝ์‚ฌํ•ญ์„ ์•Œ๋ฆด ํ•„์š”๊ฐ€ ์žˆ๋Š” ํด๋ž˜์Šค๋Š”

ChangeNotifierProvider๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ ๋ณ€๊ฒฝ์‚ฌํ•ญ์„ ์•Œ๋ฆด ํ•„์š”๊ฐ€ ์—†๋‹ค๋ฉด Provider๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.