简体   繁体   English

Flutter BloC 不刷新我的视图(计数器应用程序)

[英]Flutter BloC not refresh my view (counter app)

I'm trying BloC library with Counter test app but I have a little problem on my view when I use object to increment/decrement my counter.我正在尝试使用计数器测试应用程序使用 BloC 库,但是当我使用对象来增加/减少我的计数器时,我的视图有一些问题。 MyObject.MyProperty increment or decrement but my view not refreshed. MyObject.MyProperty 增加或减少但我的视图没有刷新。 Why?为什么?

Sample app with simple int variable.带有简单 int 变量的示例应用程序

My code with object:我的对象代码:

import 'dart:async';    
import 'package:flutter/material.dart';    
import 'package:bloc/bloc.dart';
import 'package:flutter_bloc/flutter_bloc.dart';    

void main() { 
  runApp(App());
}

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: BlocProvider(
        builder: (context) => CounterBloc(),
        child: CounterPage(),
      ),
    );
  }
}

class TestTest{
  int myProperty; 

  TestTest(){
    myProperty = 0;
  }
}


class CounterPage extends StatefulWidget {
  @override
  _CounterPageState createState() => _CounterPageState();
}

class _CounterPageState extends State<CounterPage> {
  @override
  Widget build(BuildContext context) {
    final counterBloc = BlocProvider.of<CounterBloc>(context);

    return Scaffold(
      appBar: AppBar(title: Text('Counter')),
      body: BlocBuilder<CounterBloc, TestTest>(
        builder: (context, myClassTestTest) { 
          return Center(
            child: Text(
              '${myClassTestTest.myProperty}',
              style: TextStyle(fontSize: 24.0),
            ),
          );
        },
      ),
      floatingActionButton: Column(
        crossAxisAlignment: CrossAxisAlignment.end,
        mainAxisAlignment: MainAxisAlignment.end,
        children: <Widget>[
          Padding(
            padding: EdgeInsets.symmetric(vertical: 5.0),
            child: FloatingActionButton(
              child: Icon(Icons.add),
              onPressed: () {
                counterBloc.dispatch(CounterEvent.increment);
              },
            ),
          ),
          Padding(
            padding: EdgeInsets.symmetric(vertical: 5.0),
            child: FloatingActionButton(
              child: Icon(Icons.remove),
              onPressed: () {
                counterBloc.dispatch(CounterEvent.decrement);
              },
            ),
          ),
        ],
      ),
    );
  }
}


enum CounterEvent { increment, decrement }

class CounterBloc extends Bloc<CounterEvent, TestTest> {
  @override
  TestTest get initialState => TestTest();

  @override
  Stream<TestTest> mapEventToState(CounterEvent event) async* {
    switch (event) {
      case CounterEvent.decrement:        
        currentState.myProperty -= 1;
        yield currentState; 
        break;
      case CounterEvent.increment:
        currentState.myProperty += 1;
        yield currentState; 
        break;
    }
  }
}

As you can see I edited the sample app a little just to add my class TestTest with a int property myProperty .正如您所看到的,我对示例应用程序进行了一些编辑,只是为了添加带有 int 属性myPropertyTestTest When I clic on my button the value in my object change but my view is not refreshed.当我点击我的按钮时,我的对象中的值会发生变化,但我的视图没有刷新。

How can I fix that?我该如何解决?

I found a solution to recreate my TestTest in mapEventToState but it's weird to recreate an entire object just to update a property...我找到了在mapEventToState重新创建我的 TestTest 的解决方案,但是重新创建整个对象只是为了更新属性很奇怪......

Thank you谢谢

Just posting another possible solution for future visitors.只是为未来的访问者发布另一个可能的解决方案。

If you do yield for the same state twice.如果您确实两次yield同一个状态。 Your UI won't update.您的用户界面不会更新。

For example if you have already triggered ShowDataToUser(data) from your Bloc and now after another operation you are yielding ShowDataToUser(data) again, your UI won't update.例如,如果您已经从您的 Bloc 触发了ShowDataToUser(data)并且现在在另一个操作之后您再次产生ShowDataToUser(data) ,则您的 UI 将不会更新。

A quick hack around this would be to just create a DummyState() in your Bloc and yield DummyState() everytime before you yield ShowDataToUser(data)一个快速解决这个问题的方法是在你的 Bloc 中创建一个DummyState()在每次产生ShowDataToUser(data)之前产生DummyState() ShowDataToUser(data)

Another solution apart from the quick hack around is to define a way for dart to compare and equate a class, cos currently by default ShowDataToUser is the same class, but its contents are different, but Dart doesn't know how to evaluate the content and compare them.除了快速破解之外的另一个解决方案是定义一种让 dart 比较和等同的方法,因为目前默认情况下ShowDataToUser是同一个类,但其contents不同,但 Dart 不知道如何评估内容和比较它们。

Enters Equatable进入Equatable

For this, you need to use the package : https://pub.dev/packages/equatable为此,您需要使用包: https : //pub.dev/packages/equatable

Now you have to extend your Bloc states with Equtable like:现在您必须使用 Equtable 扩展您的 Bloc 状态,例如:

class DummyState extends Equatable {}

Now, if your Bloc States are extending Equatable then you must override the function:现在,如果您的 Bloc States 正在扩展 Equatable,那么您必须覆盖该函数:

@override
  List<Object> get props => [name];

Here name is the property/field name you want to compare when comparing two same classes.这里的name是比较两个相同类时要比较的属性/字段名称。

This function tells your Bloc, how to differentiate between two same states (which might have different values in them).这个函数告诉你的 Bloc,如何区分两个相同的状态(它们可能有不同的值)。

I see you are using some kind of redux implementation and i'm not quite sure how this handles the rebuild when actions are dispatched.我看到您正在使用某种 redux 实现,我不太确定这在调度操作时如何处理重建。

As my knowledge you are dispatching an action that update some property on the widget but you are never calling setState again, so the widget is not being rebuild.据我所知,您正在调度更新小部件上某些属性的操作,但您永远不会再次调用 setState,因此不会重建小部件。

Try to call the increment or decrement actions inside a setState function.尝试在 setState 函数中调用增量或减量操作。

Something like this:像这样的东西:

onPressed: () {
 setState(() => counterBloc.dispatch(CounterEvent.decrement));
},

I have had same problem, and after googling couple of hour, I have found the solution in https://github.com/felangel/bloc/issues/203#issuecomment-480619554我遇到了同样的问题,在谷歌搜索几个小时后,我在https://github.com/felangel/bloc/issues/203#issuecomment-480619554 中找到了解决方案

As shown in the below code, The main problem is that when you yield the state, the previous state and the current state are equal, so blocBuilder have hadn't triggered.如下代码所示,主要的问题是当你yield state时,之前的状态和当前的状态是相等的,所以blocBuilder还没有触发。

case CounterEvent.decrement:        
  currentState.myProperty -= 1;
  yield currentState; 

You should copy the state, then change and yield it.您应该复制状态,然后更改并生成它。

final TestTest newState = TestTest();
newState.myProperty = currentState.myProperty;

...

case CounterEvent.decrement:        
  newState.myProperty -= 1;
  yield newState; 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Flutter bloc:更新 state 不会刷新我由 bloc 管理的视图 - Flutter bloc: updating the state does not refresh my view which is manged by bloc 使用 BLoC 模式的 Flutter 默认计数器应用程序 - Flutter default counter app using BLoC pattern 将 Flutter_bloc 8.0 的默认计数器从 Cubit 转换为 Bloc - Convert Default Flutter_bloc 8.0 Counter from Cubit to Bloc 更新示例计数器中的非即时 state - BloC Flutter - Update of the not immediate state in Example Counter - BloC Flutter 我正在借助 bloc(cubit)在 flutter 中创建异步计数器应用程序,每次计数器返回 0 时我都会发出加载 state - I am was creating async counter app in flutter with help of bloc (cubit) whet i am emitting a loading state every time counter return to 0 如何在 Flutter 应用程序的仪表板上刷新计数值? (遵循 BLoC 模式) - How can I refresh count value on my dashboard of Flutter Application? (BLoC Pattern is Followed) 使用 flutter_bloc 为 Flutter App 构建架构 - Build the architecture for a Flutter App with flutter_bloc 每当我使用 flutter_bloc 关闭我的应用程序时如何重置为初始状态/值 - How to reset to the initial state/value whenever I close my app using flutter_bloc Flutter:我是否必须为我的应用程序的每个部分创建一个 bloc? 最佳实践是什么? - Flutter: Do I have to create a bloc for each part on my app? What it the best practices? 如何将 bloc 模式与颤振应用程序集成? - how to integrat bloc pattern with a flutter app?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM