🌐
Riverpod v-2 Remote Config
良いコードかわからないが試してみた
Riverpodを使うとソースコードが減りましたね。Viewとロジックを分けることができた。
hooks_riverpodを追加する:
flutter pub add \
hooks_riverpod \
riverpod_annotation \
dev:riverpod_generator \
dev:build_runner \
dev:custom_lint \
dev:riverpod_lint
プロバイダーを作成する
AsyncData, AsyncErrorの使い方なのですが、when
のときは、(_)でしたが、switch
のときだと、同じように書けなかったので、空白にしてます。いいのかこれ???
import 'dart:async';
import 'package:firebase_remote_config/firebase_remote_config.dart';
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'remote_config_app.g.dart';
class RemoteConfigService {
final FirebaseRemoteConfig _remoteConfig;
RemoteConfigService(this._remoteConfig);
Future<void> initialize() async {
await _remoteConfig.setDefaults({
"name": "Shah",
"age": "28",
"hobby": "Coding",
});
await _remoteConfig.setConfigSettings(RemoteConfigSettings(
fetchTimeout: const Duration(seconds: 10),
minimumFetchInterval: const Duration(seconds: 10),
));
await _remoteConfig.fetchAndActivate();
}
String getString(String key) => _remoteConfig.getString(key);
Stream<RemoteConfigUpdate> get onConfigUpdated => _remoteConfig.onConfigUpdated;
}
// Providers
(keepAlive: true)
RemoteConfigService remoteConfigService(RemoteConfigServiceRef ref) {
return RemoteConfigService(FirebaseRemoteConfig.instance);
}
(keepAlive: true)
Future<void> remoteConfigInitialization(RemoteConfigInitializationRef ref) async {
final remoteConfig = ref.watch(remoteConfigServiceProvider);
await remoteConfig.initialize();
}
(keepAlive: true)
Stream<RemoteConfigUpdate> remoteConfigUpdate(RemoteConfigUpdateRef ref) {
final remoteConfig = ref.watch(remoteConfigServiceProvider);
return remoteConfig.onConfigUpdated;
}
// ------------------------------------------------------
// Widget
class RemoteConfigApp extends ConsumerWidget {
const RemoteConfigApp({super.key});
Widget build(BuildContext context, WidgetRef ref) {
final remoteConfigInitialization = ref.watch(remoteConfigInitializationProvider);
ref.listen(remoteConfigUpdateProvider, (_, __) async {
await FirebaseRemoteConfig.instance.activate();
});
final remoteConfig = ref.watch(remoteConfigServiceProvider);
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.indigo,
title: const Text('Remote Config Riverpod v-2'),
),
body: switch(remoteConfigInitialization) {
// valueがないので、()の中には何もない
AsyncData() => Padding(
padding: const EdgeInsets.symmetric(horizontal: 23.0),
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text('Riverpod v-2 Remote Config App'),
Text('Name: ${remoteConfig.getString('name')}'),
Text('Age: ${remoteConfig.getString('age')}'),
Text('Hobby: ${remoteConfig.getString('hobby')}'),
],
),
),
),
AsyncError() => const Center(child: Text('Error')),
_ => const Center(child: CircularProgressIndicator()),
},
);
}
}
main.dartを修正してビルドしてみましょう。ProviderScopeで、MyApp()をwrapしましょう。
maind.dart
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:remote_config_app/firebase_options.dart';
import 'package:remote_config_app/remote_config_app.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
runApp(const ProviderScope(child: MyApp()));
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const RemoteConfigApp(),
);
}
}
実行すると、FirebaseのRemote Configから、値を取得できているようだ。
最後に
どこにも情報がないので試行錯誤してみた💦
なんでも Riverpod使えば良いと思わないが、StatefulWidgetを嫌う人たちがいるので、合わせるとなると、riverpod, flutter_hooksを使わざるをえない💦
RemoteConfigのメリットをまだ理解できませんが、最近覚えないといけなくなったので、キャッチアップ目的で試してます。
おまけ
古いRiverpodだとこんな感じですね。
import 'package:flutter/material.dart';
import 'package:firebase_remote_config/firebase_remote_config.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
// RemoteConfigサービス
class RemoteConfigService {
final FirebaseRemoteConfig _remoteConfig;
RemoteConfigService(this._remoteConfig);
Future<void> initialize() async {
await _remoteConfig.setDefaults({
"name": "Shah",
"age": "28",
"hobby": "Coding",
});
await _remoteConfig.setConfigSettings(RemoteConfigSettings(
fetchTimeout: const Duration(seconds: 10),
minimumFetchInterval: const Duration(seconds: 10),
));
await _remoteConfig.fetchAndActivate();
}
String getString(String key) => _remoteConfig.getString(key);
Stream<RemoteConfigUpdate> get onConfigUpdated => _remoteConfig.onConfigUpdated;
}
// Providers
final remoteConfigProvider = Provider((ref) => RemoteConfigService(FirebaseRemoteConfig.instance));
final remoteConfigInitializationProvider = FutureProvider((ref) async {
final remoteConfig = ref.watch(remoteConfigProvider);
await remoteConfig.initialize();
});
final remoteConfigUpdateProvider = StreamProvider((ref) {
final remoteConfig = ref.watch(remoteConfigProvider);
return remoteConfig.onConfigUpdated;
});
// Widget
class MyHomePage extends ConsumerWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
Widget build(BuildContext context, WidgetRef ref) {
final remoteConfigInitialization = ref.watch(remoteConfigInitializationProvider);
ref.listen(remoteConfigUpdateProvider, (_, __) async {
await FirebaseRemoteConfig.instance.activate();
});
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(title),
),
body: remoteConfigInitialization.when(
data: (_) => _buildBody(ref),
loading: () => const Center(child: CircularProgressIndicator()),
error: (error, stack) => Center(child: Text('Error: $error')),
),
);
}
Widget _buildBody(WidgetRef ref) {
final remoteConfig = ref.watch(remoteConfigProvider);
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 23.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text('Welcome to the Remote Config App'),
Text('Name: ${remoteConfig.getString('name')}'),
Text('Age: ${remoteConfig.getString('age')}'),
Text('Hobby: ${remoteConfig.getString('hobby')}'),
],
),
);
}
}
Discussion