#flutter #riverpod
Вопрос:
Я перешел с RiverPod 0.4x на 1.0 стабильный, и теперь этот StateNotifier больше не обновляет состояние, даже если move()
функция вызывается (DebugPrint показывает вызов), когда анимация заканчивается. Это работало в 0.4x, но, очевидно, в улучшенной версии 1.0 RiverPod я не полностью мигрировал.
Чего мне не хватает для RiverPod 1.0 для обновления состояния, когда состояние является списком?
final animateCoversStateNotifierProvider = StateNotifierProvider.autoDispose<
AnimateCoversStateNotifier,
List<CoverAlignment>>((ref) => AnimateCoversStateNotifier());
class AnimateCoversStateNotifier extends StateNotifier<List<CoverAlignment>> {
AnimateCoversStateNotifier() : super([]);
void addCover({
required CoverAlignment alignment,
}) =>
state.add(alignment);
void move({
required int cover,
bool? readyToOpen,
bool? speechBalloonVisible,
Duration? animatedOpacityDuration,
bool? removeSpeechBalloonPadding,
}) {
debugPrint('move cover called');
Future.delayed(const Duration(milliseconds: 200), () {
if (mounted) {
state[cover].removeSpeechPadding = speechBalloonVisible != true;
state[cover].speechBalloonOpacity =
speechBalloonVisible == true ? kMaxSpeechBalloonOpacity : 0.0;
state[cover].x = CoverAlignment.randomDouble();
state[cover].y = CoverAlignment.randomDouble();
state[cover].curve = CoverAlignment.getCurve();
state[cover].seconds = CoverAlignment.randomSeconds();
state[cover].degrees = CoverAlignment.randomIntInRangeWithMinimum(
min: 0,
max: 45,
);
/// This was required to update state using RiverPod 0.4x, but no longer works in
/// RiverPod 1.0.
state = state;
}
});
}
}
В теле моего экрана сборки я использую watch
для реагирования на изменения уведомителя.
/// Display covers
final List coverAlignment =
ref.watch(animateCoversStateNotifierProvider);
РЕДАКТИРОВАТЬ: создание замороженного класса, как предлагает Remi в комментариях
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:flutter/foundation.dart';
import 'package:myapp/app/corral/models/cover_alignment_model.dart';
part 'animate_covers.freezed.dart';
class AnimateCovers extends StateNotifier<List<CoverAlignment>>
with _$AnimateCovers {
factory AnimateCovers() = _AnimateCovers;
void addCover({
required int cover,
required CoverAlignment alignment,
}) {
state.insert(cover, alignment);
}
void move({
required int cover,
bool? readyToOpen,
bool? speechBalloonVisible,
Duration? animatedOpacityDuration,
bool? removeSpeechBalloonPadding,
}) {
/// What do I do here?
}
}
Ответ №1:
Выполнение:
state = state
никогда не должен был работать.
Вы не должны изменять существующее состояние. Предполагается, что вы должны клонировать состояние
Вместо этого сделайте что-то вроде:
state[cover] = state[cover].copyWith(
removeSpeechPadding: speechBalloonVisible != true,
...
),
Вы можете сгенерировать этот copyWith
метод с помощью Freezed
Комментарии:
1. Просматриваю замороженный pub.dev/packages/ замороженный Remi. В моем сообщении я добавил свою начальную попытку создания замороженного класса моего класса AnimateCoversStateNotifier. Я не понимаю, как это сделать. Если вы можете предоставить некоторый код, это было бы очень ценно.
2. Реми, все еще застрял на этом. Я пробовал несколько разных вещей, и когда состояние представляет собой список, не похоже, что RiverPod 1.0 уведомляет слушателей об изменениях состояния списка. Даже если бы я мог начать
copyWith
работать, я не понимаю, как это может привести к тому, что StateNotifier внесет изменения в список.3. Я нашел обходной путь, поскольку я не могу заставить состояние обновляться в statenotifier. Я использую StatefulBuilder и могу вызвать setState(). В любом случае, не уверен, что это проблема в RiverPod 1.0. Спасибо за всю вашу невероятную работу, Реми.