riverpods でグローバル変数を定義している場合、変数が変わった場合、別の変数も変更する必要があったので、解決策を以下に示しておきます。
背景
30秒広告を一度見たら、「24時間広告が表示されなくなる」という機能を作る場合、
StateNotifer Class 内で別のStateProviderを呼び出す必要が出てきました。もっとわかりやすく説明すると、riverpod でグローバル変数を定義している場合、変数が変わった場合、別の変数も変更する必要が出てきたわけです。
解決策
例えば、以下の二つの変数があり、片方がもう片方に依存している関係にあるとします。
- 「アプリ内に広告を表示するかどうか」のフラグ(showAds)
- 「24時間広告を表示しないため」の時刻の変数(noAdsUntilDateTime)
上記の場合、1が2に依存しているわけです。
この場合、Dart コードは以下のようになります。
// whether showing ads or not
final showAdsProvider = StateProvider((ref) => true);
// don't show ads if user has watched rewarded ad in last 24 hours
final noAdsUntilDateTimeProvider =
StateNotifierProvider<NoAdsUntilDateTimeController, DateTime>(
(ref) => NoAdsUntilDateTimeController(ref));
class NoAdsUntilDateTimeController extends StateNotifier<DateTime> {
final StateNotifierProviderRef ref;
NoAdsUntilDateTimeController(this.ref) : super(DateTime(0)) {
init();
}
// initialize
Future<void> init() async {
// get the date that stops the ads until its time.
state = await PreferenceKeyUtil().getDateTime(
PreferenceKey.NO_ADS_UNTIL_DATE_TIME,
defaultVal: DateTime(0));
// if the no-ads time bonus is valid.
if (state.isAfter(DateTime.now())) {
// set showAds = false
ref.read(showAdsProvider.notifier).state = false;
}
}
// update no-ads date and set the current date.
void updateDateTime(DateTime dateTime) async {
state = dateTime;
PreferenceKeyUtil()
.setDateTime(PreferenceKey.NO_ADS_UNTIL_DATE_TIME, dateTime);
// set showAds = false
ref.read(showAdsProvider.notifier).state = false;
}
}
こんな感じ。もっとわかりやすく一般化すると↓
わかりやすく
aaa_StateProvider が、 BBB_StateNotifierClass に依存している場合。
(aaa_StateProvider を BBB_StateNotifierClass 内で呼び出す場合)
final aaa_Provider = StateProvider((ref) => true);
final BBB_Provider =
StateNotifierProvider<BBB_Controller, DateTime>(
(ref) => BBB_Controller(ref));
class BBB_Controller extends StateNotifier<DateTime> {
final StateNotifierProviderRef ref;
BBB_Controller(this.ref) : super(DateTime(0)) {
init();
}
Future<void> init() async {
state = dateTime;
}
void change_aaa_Provider() async {
ref.read(aaa_Provider.notifier).state = false;
}
}
みたいな感じ