Flutterにおける状態管理は、アプリケーションの成長に伴って複雑になることがよくあります。この問題を解決するために、Flutterコミュニティは様々な状態管理のパターンを提供しています。その中でも、Flutter Providerパッケージは、非常にシンプルで使いやすい状態管理の方法として人気があります。
Providerとは何ですか?
Providerは、Flutterアプリケーションで状態を管理するためのパッケージです。このパッケージは、アプリケーション全体で状態を共有するためのシンプルで効率的な方法を提供します。Providerは、InheritedWidgetを使用して状態を共有し、変更された状態を子ウィジェットに通知することができます。
Providerの使い方
Flutter Providerを使うには、まずパッケージをインストールする必要があります。pubspec.yamlファイルに以下のように追加します。
dependencies:
flutter:
sdk: flutter
provider: ^6.0.0
Providerを使用するには、以下の手順に従います。
Modelクラスを作成する
まず、状態を保持するためのModelクラスを作成します。これは、普通のDartクラスです。
class CounterModel extends ChangeNotifier {
int _counter = 0;
int get counter => _counter;
void incrementCounter() {
_counter++;
notifyListeners();
}
}
上記の例では、CounterModelクラスが作成されています。このクラスは、現在のカウンターの値を保持します。incrementCounter()メソッドを呼び出すと、カウンターの値がインクリメントされ、変更通知が発生します。
Providerを使用してModelを提供する
次に、CounterModelオブジェクトを提供するために、Providerを使用します。Providerは、buildメソッド内で使用することができます。以下のように、Providerを使用してCounterModelオブジェクトを提供することができます。
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (context) => CounterModel(),
child: MaterialApp(
home: HomeScreen(),
),
);
}
}
上記の例では、ChangeNotifierProviderを使用してCounterModelオブジェクトを提供しています。createプロパティには、新しいCounterModelオブジェクトを作成する無名関数を指定します。この無名関数は、Providerが作成されるときに一度だけ実行されます。
モデルを使用する
最後に、CounterModelオブジェクトを使用してUIをビルドします。これは、Providerを使用してCounterModelオブジェクトを取得することで行います。以下の例では、Consumerウィジェットを使用して、CounterModelオブジェクトを取得し、UIをビルドしています。
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter Provider Example'),
),
body: Center(
child: Consumer<CounterModel>(
builder: (context, counterModel, child) => Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Counter Value: ${counterModel.counter}',
style: TextStyle(fontSize: 24),
),
SizedBox(height: 16),
ElevatedButton(
onPressed: () {
counterModel.incrementCounter();
},
child: Text('Increment'),
),
],
),
),
),
);
}
}
上記の例では、Consumerウィジェットが使用されています。Consumerウィジェットは、変更されたデータを監視し、必要に応じてUIを再ビルドすることができます。CounterModelクラスのインスタンスを取得するには、Consumerウィジェットを使用し、builder関数を定義します。builder関数は、新しいUIをビルドするために使用されます。
Flutter Providerの便利な機能
Flutter Providerには、以下のような便利な機能が含まれています。
MultiProvider
MultiProviderは、複数のProviderを1つの親ウィジェットでラップするために使用されます。例えば、以下のように使用することができます。
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() {
runApp(MyApp());
}
class CounterModel with ChangeNotifier {
int _counter = 0;
int get counter => _counter;
void incrementCounter() {
_counter++;
notifyListeners();
}
}
class UserModel with ChangeNotifier {
String _name = '';
String get name => _name;
set name(String value) {
_name = value;
notifyListeners();
}
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider<CounterModel>(
create: (context) => CounterModel(),
),
ChangeNotifierProvider<UserModel>(
create: (context) => UserModel(),
),
],
child: MaterialApp(
title: 'Flutter Provider Example',
home: HomeScreen(),
),
);
}
}
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter Provider Example'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Consumer<CounterModel>(
builder: (context, counterModel, child) {
return Text(
'Counter Value: ${counterModel.counter}',
style: TextStyle(fontSize: 24),
);
},
),
Consumer<UserModel>(
builder: (context, userModel, child) {
return Text(
'User Name: ${userModel.name}',
style: TextStyle(fontSize: 24),
);
},
),
ElevatedButton(
onPressed: () {
Provider.of<CounterModel>(context, listen: false)
.incrementCounter();
Provider.of<UserModel>(context, listen: false).name =
'John Doe';
},
child: Text('Increment & Set Name'),
),
],
),
),
);
}
}
上記のコードでは、CounterModel
とUserModel
の両方がChangeNotifier
を継承しており、incrementCounter()
メソッドやname
プロパティを持っています。MyApp
クラスでは、MultiProvider
を使用して両方のモデルを提供し、HomeScreen
ウィジェットで利用します。
HomeScreen
のビルドメソッドでは、Consumer
ウィジェットを使用して、CounterModel
とUserModel
の変更を監視しています。それぞれのbuilder
関数内で、モデルの値を取得してUIを構築しています。また、ElevatedButton
が押されたときに、CounterModel
のカウンターをインクリメントし、UserModel
の名前を設定しています。
ProxyProvider
ProxyProviderは、1つのProviderから別のProviderを作成するために使用されます。以下のように使用することができます。
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() {
runApp(MyApp());
}
class CounterModel with ChangeNotifier {
int _counter = 0;
int get counter => _counter;
void incrementCounter() {
_counter++;
notifyListeners();
}
}
class UserModel {
String _name = '';
String get name => _name;
set name(String value) {
_name = value;
}
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider<CounterModel>(
create: (context) => CounterModel(),
),
ProxyProvider<CounterModel, UserModel>(
update: (context, counterModel, userModel) =>
UserModel()..name = 'John Doe',
),
],
child: MaterialApp(
title: 'Flutter Provider Example',
home: HomeScreen(),
),
);
}
}
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter Provider Example'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Consumer<CounterModel>(
builder: (context, counterModel, child) {
return Text(
'Counter Value: ${counterModel.counter}',
style: TextStyle(fontSize: 24),
);
},
),
Consumer<UserModel>(
builder: (context, userModel, child) {
return Text(
'User Name: ${userModel.name}',
style: TextStyle(fontSize: 24),
);
},
),
ElevatedButton(
onPressed: () {
Provider.of<CounterModel>(context, listen: false)
.incrementCounter();
},
child: Text('Increment Counter'),
),
],
),
),
);
}
}
このコードでは、CounterModel
とUserModel
を定義し、ChangeNotifier
を継承しています。CounterModel
はカウンターの状態を管理し、incrementCounter()
メソッドを提供しています。UserModel
はユーザーの名前を管理する単純なモデルです。
MyApp
クラスでは、MultiProvider
を使用して複数のプロバイダーを提供します。ChangeNotifierProvider
を使用してCounterModel
を提供し、ProxyProvider
を使用してCounterModel
からUserModel
を生成します。update
コールバック内で新しいUserModel
インスタンスを作成し、名前を設定しています。
HomeScreen
のビルドメソッドでは、Consumer
ウィジェットを使用してCounterModel
とUserModel
の変更を監視します。CounterModel
のカウンターとUserModel
の名前を表示し、ElevatedButton
が押されるとCounterModel
のカウンターをインクリメントします。
まとめ
Flutter Providerは、Flutterアプリケーションで状態を管理するための非
常に手軽で強力なツールです。ChangeNotifierProviderを使用して、モデルクラスを提供することができ、Consumerウィジェットを使用して、変更を監視し、必要に応じてUIを再ビルドすることができます。また、MultiProviderを使用して複数のProviderを1つの親ウィジェットでラップすることができ、ProxyProviderを使用して1つのProviderから別のProviderを作成することができます。
Flutter Providerは、簡単に導入でき、状態管理を簡単に実装できるため、Flutterアプリケーションの開発には必要不可欠なツールです。是非、今後の開発に取り入れてみてください。
Provider以外の状態管理の方法は以下のページおよび、ページ内リンクの記事で詳しく説明していますので、参考にしてみて下さい。