久しぶりの投稿です。
最近、業務でRiverpodを使っている影響でちょっとだけRiverpodのことが分かってきました。
Flutter x Riverpod
Flutter x RiverpodでのTextFieldの入力中の制御について解説します。
まずはサンプルアプリの画面を用意します。
main.dart
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
const MyHomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('サンプル'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Row(
children: [
Text('メールアドレス'),
SizedBox(
width: 20.0,
),
Expanded(
child: TextFormField(
enabled: true,
style: TextStyle(color: Colors.black),
obscureText: false,
maxLines: 1,
),
),
],
),
ElevatedButton(
onPressed: () {
print('送信');
},
child: Text('送信')
)
],
),
),// This trailing comma makes auto-formatting nicer for build methods.
);
}
}
ビルドすると次のような画面が表示されます。
テキスト入力とボタンが存在します。
ここからRiverpodをインストールします。
pubspec.yamlを開いてRiverpodをインストールします。
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^1.0.2
flutter_riverpod: ^0.14.0+3
バージョンは意味なく最新版を指定しています。
今回は、ボタンをタップするとコンソールに入力したメールアドレスが表示される機能を実装します。
メールアドレス用のStateProviderの定義
main.dartに次のコードを定義します。
main.dart
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
// emailのcontrollerをStateProviderで定義する
final emailControllerStateProvider = StateProvider.autoDispose((ref) {
return TextEditingController(text: '');
});
void main() {
runApp(MyApp());
}
位置関係を明確にするためにimport文とmain関数の間に宣言しました。
今回はTextEditingControllerを使う形にします。(このために別の処理で泥沼にハマりました。)
RiverpodをWidget全体で使えるようにProviderScopeを定義する
Riverpodを使うための準備はまだあります。
Riverpodを適用させたいウィジェットにProviderScopeで囲う必要があります。
main.dart
void main() {
runApp(
ProviderScope(
child: MyApp(),
),
);
}
StatelessWidgetをConsumerWidgetに書き換える
次に定義したStateProviderを監視するためにStatelessWidgetの部分をConsumerWidgetに書き換えます。これでwatch関数が使えるようになります。
class MyHomePage extends ConsumerWidget
メールアドレスの変更を監視するためにbuild関数を次のように変更します。
main.dart
@override
Widget build(BuildContext context, ScopedReader watch) {
// 中身は TextEditingController
final emailControllerProvider = watch(emailControllerStateProvider);
return Scaffold(
appBar: AppBar(
title: Text('サンプル'),
),
そして、TextFormFieldのcontrollerにこれをセットすればProviderとControllerが連携されます。
main.dart
Expanded(
child: TextFormField(
controller: emailControllerProvider.state,
enabled: true,
style: TextStyle(color: Colors.black),
obscureText: false,
maxLines: 1,
),
),
あとは、送信ボタンをタップした時に定義したProviderをprintします。
main.dart
ElevatedButton(
onPressed: () {
print(emailControllerProvider.state.text);
},
child: Text('送信')
)
これで例えば、メールアドレスのテキスト入力欄に「sample@gmail.com」を入力して送信ボタンをタップするとコンソールに「sample@gmail.com」が表示されます。
Syncing files to device iPhone 12...
flutter: sample@gmail.com
これでRiverpodの基礎的な使い方です。ここから先がどんどん難しくなります。
Riverpod使いだしてまだ日が浅いので、ちょっと変更するにしても色々苦戦します。
全体のソースコード
全体のソースコードはこちらになります。
main.dart
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
// emailのcontrollerをStateProviderで定義する
final emailControllerStateProvider = StateProvider.autoDispose((ref) {
return TextEditingController(text: '');
});
void main() {
runApp(
ProviderScope(
child: MyApp(),
),
);
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends ConsumerWidget {
const MyHomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context, ScopedReader watch) {
// 中身は TextEditingController
final emailControllerProvider = watch(emailControllerStateProvider);
return Scaffold(
appBar: AppBar(
title: Text('サンプル'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Row(
children: [
Text('メールアドレス'),
SizedBox(
width: 20.0,
),
Expanded(
child: TextFormField(
controller: emailControllerProvider.state,
enabled: true,
style: TextStyle(color: Colors.black),
obscureText: false,
maxLines: 1,
),
),
],
),
ElevatedButton(
onPressed: () {
print(emailControllerProvider.state.text);
},
child: Text('送信')
)
],
),
),// This trailing comma makes auto-formatting nicer for build methods.
);
}
}