Providerを勉強し直してみた...
今まで、ChageNotifire、Consumerし使ったことがなかった。
Provider.of(context);だとか、context.watch<>();って何だろうと考えていた???
こちらの公式ドキュメントで解説されていた。
https://pub.dev/documentation/provider/latest/provider/ChangeNotifierProvider-class.html
最近になって何となくわかってきた...
とりえずサンプルを作ってプログラムの挙動を調べてみた...
person_model.dart
import 'package:flutter/foundation.dart';
class Person with ChangeNotifier {
final String firstName = "Jboy";
final String lastName = "Hashimoto";
int age = 0;
void say() {
// コンソールに表示
print("Hello Person!!!");
notifyListeners();
}
void addAge() {
age++;
notifyListeners();
}
}
pet_model.dart
import 'package:flutter/foundation.dart';
class Pet with ChangeNotifier {
final String petName = 'ポチ';
int bowbow = 0;
void bowCount() {
// 吠えた数
bowbow++;
notifyListeners();
}
}
home_page.dart
import 'package:flutter/material.dart';
import 'package:person_mvvm/model/person_model.dart';
import 'package:person_mvvm/model/pet_model.dart';
import 'package:provider/provider.dart';
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: [
Text(
'私の名前は、${context.watch<Person>().firstName}',
style: const TextStyle(fontSize: 20.0),
),
const SizedBox(height: 10.0),
Text(
'私の苗字は、${context.select<Person, String>((Person person) => person.lastName)}',
style: const TextStyle(fontSize: 20.0),
),
Text(
'年齢は、${context.select<Person, int>((Person person) => person.age)}',
style: const TextStyle(fontSize: 20.0),
),
const SizedBox(height: 10.0),
ElevatedButton(
onPressed: () => context.read<Person>().addAge(),
child: const Text(
'歳をとっていく...',
style: TextStyle(fontSize: 20.0),
)),
const SizedBox(height: 10.0),
ElevatedButton(
onPressed: () => context.read<Person>().say(),
child: const Icon(Icons.add_call)),
const SizedBox(height: 10.0),
Text(
'Jboyの愛犬の名前は、${context.watch<Pet>().petName}',
style: const TextStyle(fontSize: 20.0),
),
const SizedBox(height: 10.0),
Text('吠えた回数は、${context.select<Pet, int>((Pet pet) => pet.bowbow)}'),
ElevatedButton(
onPressed: () => context.read<Pet>().bowCount(),
child: const Icon(Icons.add_alert)),
],
),
),
);
}
}
main.dart
import 'package:flutter/material.dart';
import 'package:person_mvvm/model/person_model.dart';
import 'package:person_mvvm/model/pet_model.dart';
import 'package:provider/provider.dart';
import 'views/home_page.dart';
void main() {
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => Person()),
ChangeNotifierProvider(create: (_) => Pet()),
],
child: const MyApp(),
),
);
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Person mvvm',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const HomePage(),
);
}
}
今回、何でこんなコードを書いたのかというと、pub.devのProviderのExampleのサンプルコードを見て、Flutter大学のProviderと書き方が違って、ちんぷんかんぷんだったから!!!
これが、どんな意味なのか最近までわからなかった???
void main() {
runApp(
/// Providers are above [MyApp] instead of inside it, so that tests
/// can use [MyApp] while mocking the providers
MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => Counter()),
],
child: const MyApp(),
),
);
}
公式のドキュメント
解説を日本語に訳すと、「複数のプロバイダを1つのリニアなウィジェットツリーに統合するプロバイダです。可読性を高め、プロバイダを何重にもネストしなければならないという定型的なコードを減らすために使用されます。」
どういうことかというと、複数のモデルのクラスをMultiProviderの中に書いて、呼び出すことができる。
だと思う...
私が書いたサンプルコードは、こんな感じで、PersonモデルとPetモデルを呼び出している。
この書き方を知ったのは、ミンプロっていう以前Udemyで購入したProviderの講座でした。
やっと、pub.devのサンプルコードの意味が理解できた...
void main() {
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => Person()),
ChangeNotifierProvider(create: (_) => Pet()),
],
child: const MyApp(),
),
);
}
最後に
コピペばかりせずに、公式ドキュメントを見るようにするのが、良いのだがどうしてもわからないときは、メンターを雇った方がいいかもしれないですね。