颤振:BLoC Builder 未更新,尽管我在调试器中看到新的/不同的状态
Posted
技术标签:
【中文标题】颤振:BLoC Builder 未更新,尽管我在调试器中看到新的/不同的状态【英文标题】:flutter: BLoC Builder not updating, though I see new/different state in debugger 【发布时间】:2021-01-05 15:05:23 【问题描述】:我今天的第二个奇怪事件。当我在 bloc.dart(库,而不是我的文件)中跟踪调试器时,我看到 transition.nextState == state && _emitted
是 false
,它不会更新我的小部件(nextState 的列表大小为 2,状态为 10 - _emitted 为真) .据我了解,构建器应该没问题,还有其他地方可以查看它为什么不更新吗?
在我展示代码之前先解释一下逻辑
我在应用启动时获取我的数据
BlocProvider(create: (context) =>
LogicGraphsPStmntBloc(logicGraphsRepository:
logicGraphsRepository)..add(LogicGraphsNextProblemRequested()),
这会返回一个包含 10 个字符串的列表,我将其存储在我的 _bloc.dart 文件中(不确定这是否是最先进的)
这 10 个字符串通过状态 LogicGraphsPStmntLoadSuccess(statements)
发送并正确呈现为按钮
如果我单击一个按钮,则只会显示第一个和选定的字符串。使用onPressed: () BlocProvider.of<LogicGraphsPStmntBloc>(context).add(LogicGraphsPStmntCollapsed(statement: index-1));,
正确触发事件
这会正确触发状态yield LogicGraphsPStmntLoadSuccess(statementsShown);
,现在列表中只有 2 个元素(与第 3 步中的 10 个元素相比),但不会导致重新渲染
如果我使用调试器进入状态,我可以看到两个状态具有不同数量的元素。
我的状态
abstract class LogicGraphsPStmntState extends Equatable
const LogicGraphsPStmntState();
@override
List<Object> get props => [];
class LogicGraphsPStmntLoadSuccess extends LogicGraphsPStmntState
const LogicGraphsPStmntLoadSuccess([this.statements = const []]);
final List<String> statements;
@override
List<Object> get props => [];
@override
String toString() => 'LogicGraphsPStmntLoadSuccess statements: $statements ';
我的块(不完全是,因为我的子函数中释放状态的代码没有达到my other issue 中描述的那样。所以目前我在 mapEventToState= 中将这些子函数行作为意大利面条=
class LogicGraphsPStmntBloc extends Bloc<LogicGraphsPStmntEvent, LogicGraphsPStmntState>
LogicGraphsPStmntBloc(@required this.logicGraphsRepository) : super(LogicGraphsPStmntInProgress());
final LogicGraphsRepository logicGraphsRepository;
List<String> statements;
int currentProblem = -1;
@override
Stream<LogicGraphsPStmntState> mapEventToState(LogicGraphsPStmntEvent event) async*
if (event is LogicGraphsNextProblemRequested)
_mapLGPStmntNewProblemRequested();
_mapLGPStmntLoadRequested(currentProblem);
else if (event is LogicGraphsPStmntLoadRequested)
_mapLGPStmntLoadRequested(currentProblem);
else if (event is LogicGraphsPStmntCollapsed)
_mapLGPStmntCollapseRequested(event);
Stream<LogicGraphsPStmntState> _mapLGPStmntNewProblemRequested() async*
try
currentProblem =
await getNextProblem(currentProblem == null ? -1 : currentProblem);
statements =
await logicGraphsRepository.getProblemStmntList(currentProblem);
_mapLGPStmntLoadRequested(currentProblem);
catch (_)
yield LogicGraphsPStmntLoadFailure();
Stream<LogicGraphsPStmntState> _mapLGPStmntLoadRequested(int problem) async*
try
yield LogicGraphsPStmntLoadSuccess(statements);
catch (_)
yield LogicGraphsPStmntLoadFailure();
Stream<LogicGraphsPStmntState> _mapLGPStmntCollapseRequested(
LogicGraphsPStmntCollapsed event) async*
List<String> statementsShown = [];
statementFocussed = event.statement;
statementsShown.add(statements[0]);
statementsShown.add(statements[statementFocussed]);
yield LogicGraphsPStmntLoadSuccess(statementsShown);
我的小部件
class LogicGraphpage extends StatelessWidget
final LogicGraphsRepository logicGraphsRepository = LogicGraphsRepository(
logicGraphsApiClient: LogicGraphsApiClient());
@override
Widget build(BuildContext context)
return CupertinoPageScaffold(
child: BlocProvider(
create: (context) =>
LogicGraphsPStmntBloc(logicGraphsRepository: logicGraphsRepository)
..add(LogicGraphsNextProblemRequested()),
child:BlocBuilder<LogicGraphsPStmntBloc, LogicGraphsPStmntState>(
builder: (context, state)
if (state is LogicGraphsPStmntLoadSuccess)
final List<String> statements = state.statements;
return ListView.builder(
itemCount: statements.length,
itemBuilder: (BuildContext context, int index)
return CupertinoButton(
padding: EdgeInsets.all(0),
child: Text(statements[index])
onPressed: () BlocProvider.of<LogicGraphsPStmntBloc>(context).add(LogicGraphsPStmntCollapsed(statement: index-1));,
);
);
else return Container();
)
),
);
bloc.dart 库中的函数,我假设新状态已发出。您会看到if (transition.nextState == state && _emitted) return;
行。下一个状态有 2 个元素,状态有 10 个,_emitted 为真,所以我假设代码继续。而是触发返回并跳过带有emit(transition.nextState);
的行。
任何帮助都非常感谢,因为这是我第一次使用 BLoC/equatable 和 Flutter 的经验,总的来说对我来说还是很新的。但我正在进步!
void _bindEventsToStates()
_transitionSubscription = transformTransitions(
transformEvents(
_eventController.stream,
(event) => mapEventToState(event).map(
(nextState) => Transition(
currentState: state,
event: event,
nextState: nextState,
),
),
),
).listen(
(transition)
if (transition.nextState == state && _emitted) return; // <<<<<<<<<<<
try
onTransition(transition);
emit(transition.nextState);
on dynamic catch (error, stackTrace)
onError(error, stackTrace);
_emitted = true;
,
onError: onError,
);
【问题讨论】:
【参考方案1】:我猜集团无法区分LogicGraphsPStmntLoadSuccess(statements)
和LogicGraphsPStmntLoadSuccess(statementsShown)
,因为它们是相同的状态,我认为它无法发现不同参数之间的差异。
所以我建议这样做:
在产生LogicGraphsPStmntLoadSuccess(statementsShown)
之前尝试产生一个“切换”状态,就像我之前不知道LogicGraphsPStmntChangeStatement
一样。
所以:
yield LogicGraphsPStmntChangeStatement;
yield LogicGraphsPStmntLoadSuccess(statementsShown);
这应该可以解决问题。
【讨论】:
你完全正确!所以状态变化意味着状态的变化,而不是状态的变化。因此,当我对此进行调试时, nextstate == state 不会比较值,而是比较状态的“类型”。是什么让我想知道:如果我在线获取数据并在 2 秒后返回一个块,在 10 秒后返回一些块,loadSuccess 状态会等待 10 秒并显示所有数据,它会在 2 秒后提供第一个块,其余的稍后提供还是停止交付2s 后(不确定这种传输中是否存在某种 EOF)? 感谢您提供此解决方案,但还有其他方法吗?我的意思是有没有办法让 bloc 知道状态已经改变,因为状态内的数据发生了变化? 是的,有办法,看看这篇文章:medium.com/flutterworld/…以上是关于颤振:BLoC Builder 未更新,尽管我在调试器中看到新的/不同的状态的主要内容,如果未能解决你的问题,请参考以下文章