🤖
【Flutter】 Provider
Provider
- プロバイダーウィジェットタイプの中で最も基本
- ウィジェットツリーの任意の場所に値を提供
- 値の変更キャッチして再描画はしない
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return Provider<MyModel>(
create: (context) => MyModel(),
child: MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Flutter Demo')
),
backgroundColor: Colors.white,
body: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
padding: const EdgeInsets.all(20),
color: Colors.green[200],
child: Consumer<MyModel>(
builder: (context, myModel, child) {
return RaisedButton(
child: Text('Do something'),
onPressed: () {
myModel.doSomething();
},
);
}
)
),
Container(
padding: const EdgeInsets.all(35),
color: Colors.blue[200],
child: Consumer<MyModel>(
builder: (context, myModel, child) {
return Text(myModel.someValue);
},
)
)
]
)
)
)
);
}
}
class MyModel {
String someValue = 'hello';
void doSomething() {
someValue = 'Goodbye';
print(someValue);
}
}
ChangeNotifierProvider
- 値の変更をリッスンする。ウィジェット再構築
- モデルクラスではChangeNotifier ミックスインする必要あり
- notifyListeners()を呼び出すとChangeNotifierProviderが通知され、Consumerがウィジェットを再描画してくれる
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider<MyModel>(
create: (context) => MyModel(),
child: MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Flutter Demo')
),
backgroundColor: Colors.white,
body: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
padding: const EdgeInsets.all(20),
color: Colors.green[200],
child: Consumer<MyModel>(
builder: (context, myModel, child) {
return RaisedButton(
child: Text('Do something'),
onPressed: () {
myModel.doSomething();
},
);
}
)
),
Container(
padding: const EdgeInsets.all(35),
color: Colors.blue[200],
child: Consumer<MyModel>(
builder: (context, myModel, child) {
return Text(myModel.someValue);
},
)
)
]
)
)
)
);
}
}
class MyModel with ChangeNotifier {
String someValue = 'hello';
void doSomething() {
if (someValue == 'hello') {
someValue = 'Goodbye';
} else {
someValue = 'hello';
}
print(someValue);
notifyListeners();
}
}
FutureProvider
- 指定した Future のタスクが完了するのをリッスンすし、ウィジェットを再描画(再構築)
- 主に、HTTPリクエストやローカルファイルの読み込みなどで利用する
- AsyncValue という Riverpod 独自のオブジェクトで返される
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return FutureProvider<MyModel>(
initialData: MyModel(value: 'default value'),
create: (context) => someAsyncFunctionToGetMyModel(),
child: MaterialApp(
home: Scaffold(
title: Text('Flutter Demo')
),
backgroundColor: Colors.white,
body: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
padding: const EdgeInsets.all(20),
color: Colors.green[200],
child: Consumer<MyModel>(
builder: (context, myModel, child) {
return RaisedButton(
child: Text('Do something'),
onPressed: () {
myModel.doSomething();
},
);
}
)
),
Container(
padding: const EdgeInsets.all(35),
color: Colors.blue[200],
child: Consumer<MyModel>(
builder: (context, myModel, child) {
return Text(myModel.someValue);
},
)
)
]
)
)
)
}
}
Future<MyModel> someAsyncFunctionToGetMyModel() async {
await Future.delayed(Duration(seconds: 5));
return MyModel(value: 'new data');
}
class MyModel {
String someValue = 'hello';
MyModel({ value }) {
someValue = value;
}
Future<void> doSomething() async {
await Future.delayed(Duration(seconds: 2));
// ここが変更されてもウジェットの値は変わらない(際描画されるない)」
someValue = 'Goodbye';
print(someValue);
}
}
Discussion