| ページ一覧 | ブログ | twitter |  書式 | 書式(表) |

MyMemoWiki

「Flutter Riverpod」の版間の差分

提供: MyMemoWiki
ナビゲーションに移動 検索に移動
 
(同じ利用者による、間の13版が非表示)
1行目: 1行目:
 
| [[Flutter]] | [[Dart]] | [https://www.typea.info/blog/index.php/category/flutter/ ブログカテゴリ(Flutter)] | [[Android Studio]] | [[Flutter macos]] | [[FlutterFire]] | [[Flutter 手順]] |  
 
| [[Flutter]] | [[Dart]] | [https://www.typea.info/blog/index.php/category/flutter/ ブログカテゴリ(Flutter)] | [[Android Studio]] | [[Flutter macos]] | [[FlutterFire]] | [[Flutter 手順]] |  
 
==Flutter Riverpod==
 
==Flutter Riverpod==
 +
{{amazon|B09754L28H}}
 +
*https://pub.dev/packages/flutter_riverpod
 +
 +
==基本==
 +
*[https://riverpod.dev/docs/getting_started はじめに]
 +
*[https://pub.dev/documentation//flutter_riverpod/latest/flutter_riverpod/flutter_riverpod-library.html flutter_riverpod]
 +
===データの受け渡し===
 +
----
 +
Providerをグローバルに定義し、データを受け渡す
 +
====データを渡す====
 +
----
 +
{|class="wikitable"
 +
!種類
 +
!目的
 +
|-
 +
| Provider
 +
| 任意のデータを渡す
 +
|-
 +
| [https://pub.dev/documentation/riverpod/latest/riverpod/FutureProvider-class.html FutureProvider]
 +
| Futureから取得する任意のデータを渡す
 +
|-
 +
| Stream Provider
 +
| Streamから取得する任意のデータを渡す
 +
|-
 +
| [https://pub.dev/documentation/riverpod/latest/riverpod/StateProvider-class.html StateProvider]
 +
| 変更可能な任意のデータを渡す
 +
|-
 +
| StateNotifireProvider
 +
| StateNotifireProviderから取得する任意のデータを渡す
 +
|-
 +
| ScopedProvider
 +
| 場所に応じて異なる任意のデータを渡す
 +
|-
 +
|}
 +
 +
====データを受け取る====
 +
----
 +
{|class="wikitable"
 +
!種類
 +
!目的
 +
|-
 +
| [https://pub.dev/documentation//flutter_riverpod/latest/flutter_riverpod/ConsumerWidget-class.html ConsumerWidget]
 +
| 継承することでデータを受け取れるWidget
 +
|-
 +
| [https://pub.dev/documentation//flutter_riverpod/latest/flutter_riverpod/Consumer-class.html Consumer]
 +
| コールバック内でデータを受け取れるWidget
 +
|-
 +
| useProvider()
 +
| flutter_hooksを利用し、HookWidgetを継承したWidgetでデータを受け取れる関数
 +
|-
 +
| context.read()
 +
| BuildContextからデータを受け取れる関数(ただしデータの変更通知は受け取れない)
 +
|-
 +
| ProviderContainer
 +
| Flutterに依存しない形でデータを受け取れる
 +
|-
 +
|}
 +
 +
===基本===
 +
----
 +
[[FlutterFire]]
 +
====pubspec.yaml=====
 +
<pre>
 +
  flutter:
 +
    sdk: flutter
 +
  flutter_riverpod: ^0.14.0+3
 +
  firebase_core: ^1.7.0
 +
  firebase_auth: ^3.1.3
 +
  json_annotation: ^4.0.1
 +
 +
dev_dependencies:
 +
  flutter_test:
 +
    sdk: flutter
 +
  json_serializable: ^4.1.3
 +
  build_runner: ^2.1.1
 +
</pre>
 +
====Main====
 +
*main.dart
 +
<pre>
 +
import 'package:firebase_core/firebase_core.dart';
 +
import 'package:flutter_riverpod/flutter_riverpod.dart';
 +
import 'package:flutter/material.dart';
 +
import 'package:repbuilder/provider/providers.dart';
 +
import 'package:repbuilder/widget/widgets.dart';
 +
import 'package:repbuilder/screen/sign_in/sigin_in.dart';
 +
import 'package:repbuilder/screen/person_list/person_list.dart';
 +
 +
void main() async {
 +
  // Flutter の初期化処理を待つ
 +
  WidgetsFlutterBinding.ensureInitialized();
 +
  // Firebaseの初期化(非同期)を待つ
 +
  await Firebase.initializeApp();
 +
 
 +
  runApp(ProviderScope(child: RepBuilder()));
 +
}
 +
 +
class RepBuilder extends StatelessWidget {
 +
  // This widget is the root of your application.
 +
  @override
 +
  Widget build(BuildContext context) {
 +
    return MaterialApp(
 +
      title: 'Report Builder',
 +
      theme: ThemeData(
 +
        primarySwatch: Colors.blue,
 +
      ),
 +
      home: Consumer(
 +
        builder: (context,  watch, child) {
 +
          final user = watch(userProvider);
 +
          return user.when(
 +
            data: (user) => (user == null) ? SignInScreen() : PersonLIst(),
 +
            loading: () => loadingWidget(),
 +
            error: (e, stackTrace) => errorWidget(context, e, stackTrace),
 +
          );
 +
        },
 +
      )
 +
    );
 +
  }
 +
}
 +
</pre>
 +
 +
====Model====
 +
<pre>
 +
import 'package:json_annotation/json_annotation.dart';
 +
part 'person.g.dart';
 +
 +
@JsonSerializable()
 +
class Person {
 +
  String? id;
 +
  String? name;
 +
  DateTime? createdAt;
 +
 +
  Person({this.id, this.name});
 +
 +
  factory Person.fromJson(Map<String, dynamic> json) => _$PersonFromJson(json);
 +
  Map<String, dynamic> toJson() => _$PersonToJson(this);
 +
}</pre>
 +
*json_annotation
 +
<pre>
 +
$ flutter pub run build_runner build
 +
</pre>
 +
 +
====Repository====
 +
<pre>
 +
import 'package:firebase_auth/firebase_auth.dart';
 +
import 'package:repbuilder/model/person.dart';
 +
 +
class PersonRepository {
 +
  final User user;
 +
  PersonRepository(this.user);
 +
 +
  List<Person> getPersonList() {
 +
    // DUMMY
 +
    return new List.of([new Person(id:"id1",name:this.user.email), new Person(id:"id2",name:this.user.email)]);
 +
  }
 +
}
 +
</pre>
 +
 +
====Provider====
 +
<pre>
 +
import 'package:firebase_auth/firebase_auth.dart';
 +
import 'package:flutter_riverpod/flutter_riverpod.dart';
 +
import 'package:repbuilder/repository/repositories.dart';
 +
 +
final userProvider = StreamProvider.autoDispose((ref) {
 +
  return FirebaseAuth.instance.authStateChanges();
 +
});
 +
 +
final personRepositoryProvider = Provider.autoDispose((ref) {
 +
  final User? user = ref.watch(userProvider).data?.value;
 +
  return user == null ? null : PersonRepository(user);
 +
});
 +
</pre>
 +
 +
====Consumer====
 +
<pre>
 +
import 'package:flutter/material.dart';
 +
import 'package:repbuilder/provider/providers.dart';
 +
import 'package:flutter_riverpod/flutter_riverpod.dart';
 +
 +
class PersonListPage extends StatelessWidget {
 +
  @override
 +
  Widget build(BuildContext context) {
 +
    return Scaffold(
 +
      appBar: AppBar(
 +
          title: Text('TODO APP TITLE'),
 +
      ),
 +
      body: _PersonListView()
 +
  );
 +
  }
 +
}
 +
class _PersonListViewState extends ConsumerWidget {
 +
  @override
 +
  Widget build(BuildContext context, ScopedReader watch) {
 +
    final personRep = watch(personRepositoryProvider);
 +
    var persons = personRep?.getPersonList();
 +
    return buildDataTable(persons!);
 +
  }
 +
  Widget buildDataTable(List<Person> persons) {
 +
        :
 +
  }
 +
}
 +
</pre>

2021年11月1日 (月) 12:35時点における最新版

Flutter Riverpod

基本

データの受け渡し


Providerをグローバルに定義し、データを受け渡す

データを渡す


種類 目的
Provider 任意のデータを渡す
FutureProvider Futureから取得する任意のデータを渡す
Stream Provider Streamから取得する任意のデータを渡す
StateProvider 変更可能な任意のデータを渡す
StateNotifireProvider StateNotifireProviderから取得する任意のデータを渡す
ScopedProvider 場所に応じて異なる任意のデータを渡す

データを受け取る


種類 目的
ConsumerWidget 継承することでデータを受け取れるWidget
Consumer コールバック内でデータを受け取れるWidget
useProvider() flutter_hooksを利用し、HookWidgetを継承したWidgetでデータを受け取れる関数
context.read() BuildContextからデータを受け取れる関数(ただしデータの変更通知は受け取れない)
ProviderContainer Flutterに依存しない形でデータを受け取れる

基本


FlutterFire

pubspec.yaml=

  flutter:
    sdk: flutter
  flutter_riverpod: ^0.14.0+3
  firebase_core: ^1.7.0
  firebase_auth: ^3.1.3
  json_annotation: ^4.0.1

dev_dependencies:
  flutter_test:
    sdk: flutter
  json_serializable: ^4.1.3
  build_runner: ^2.1.1

Main

  • main.dart
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter/material.dart';
import 'package:repbuilder/provider/providers.dart';
import 'package:repbuilder/widget/widgets.dart';
import 'package:repbuilder/screen/sign_in/sigin_in.dart';
import 'package:repbuilder/screen/person_list/person_list.dart';

void main() async {
  // Flutter の初期化処理を待つ
  WidgetsFlutterBinding.ensureInitialized();
  // Firebaseの初期化(非同期)を待つ
  await Firebase.initializeApp();
  
  runApp(ProviderScope(child: RepBuilder()));
}

class RepBuilder extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Report Builder',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Consumer(
        builder: (context,  watch, child) { 
          final user = watch(userProvider);
          return user.when(
            data: (user) => (user == null) ? SignInScreen() : PersonLIst(), 
            loading: () => loadingWidget(), 
            error: (e, stackTrace) => errorWidget(context, e, stackTrace),
          );
        },
      )
    );
  }
}

Model

import 'package:json_annotation/json_annotation.dart';
part 'person.g.dart';

@JsonSerializable()
class Person {
  String? id;
  String? name;
  DateTime? createdAt;

  Person({this.id, this.name});

  factory Person.fromJson(Map<String, dynamic> json) => _$PersonFromJson(json);
  Map<String, dynamic> toJson() => _$PersonToJson(this);
}
  • json_annotation
$ flutter pub run build_runner build

Repository

import 'package:firebase_auth/firebase_auth.dart';
import 'package:repbuilder/model/person.dart';

class PersonRepository {
  final User user;
  PersonRepository(this.user);

  List<Person> getPersonList() {
    // DUMMY 
    return new List.of([new Person(id:"id1",name:this.user.email), new Person(id:"id2",name:this.user.email)]);
  }
}

Provider

import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:repbuilder/repository/repositories.dart';

final userProvider = StreamProvider.autoDispose((ref) {
  return FirebaseAuth.instance.authStateChanges();
});

final personRepositoryProvider = Provider.autoDispose((ref) {
  final User? user = ref.watch(userProvider).data?.value;
  return user == null ? null : PersonRepository(user);
});

Consumer

import 'package:flutter/material.dart';
import 'package:repbuilder/provider/providers.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

class PersonListPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
          title: Text('TODO APP TITLE'),
      ),
      body: _PersonListView()
   );
  }
}
class _PersonListViewState extends ConsumerWidget {
  @override
  Widget build(BuildContext context, ScopedReader watch) {
    final personRep = watch(personRepositoryProvider);
    var persons = personRep?.getPersonList();
    return buildDataTable(persons!);
  }
  Widget buildDataTable(List<Person> persons) {
         :
  }
}