Bloc流未正确更新 [英] Bloc stream not updating properly

查看:75
本文介绍了Bloc流未正确更新的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是直接来自以下方面的内容: Bloc体系结构"; getter x被调用为null." 由@nonybrighto

This is a direct follow on from: Bloc architecture "the getter x was called on null." which was resolved by @nonybrighto

现在的问题是,尽管我再也没有从应用程序中收到任何错误,但是由于颜色没有更新,因此逻辑在某处失败了,它们只是保持蓝色.如果我调用:colorBloc.changeColor();从回调到子项本身(下拉菜单),或者直接从父项进行回调,它实际上并没有更新这些小部件按钮的颜色.它们总是蓝色.

The issue now is that although I am getting no error from the application any more, the logic is failing somewhere as the colours are not updating, they just remain blue. If I call: colorBloc.changeColor(); from either a callback to the child (dropdownmenu) itself, or directly from the parent, it just doesn't actually update the colours of these widget buttons. They are always blue.

要让按钮小部件实际更新,还需要做些其他事情吗?

Is there something additional I have to do to get my button widgets to actually update?

是否需要其他信息?

父类和子类,以及我如何尝试使用集团.

The parent and child classes, and how I am trying to use the bloc.

dropdownmenu.dart

dropdownmenu.dart

import 'package:flutter/material.dart';
import 'dart:math';
import 'package:ultimate_mtg/model/colorBloc.dart';
import 'package:ultimate_mtg/model/blocprovider.dart';

// ignore: camel_case_types
class dropDownMenu extends StatefulWidget {
  final Function() onPressed;
  final String tooltip;
  final IconData icon;
  final _callback;

  dropDownMenu({Key key, this.onPressed, this.tooltip, this.icon, @required void singlePlayerCallbacks(String callBackType), @required StatefulWidget styleMenu }  ):
      _callback = singlePlayerCallbacks;

  @override
  dropDownMenuState createState() => dropDownMenuState();
}

// ignore: camel_case_types
class dropDownMenuState extends State<dropDownMenu>
    with SingleTickerProviderStateMixin {
  bool isOpened = false;
  AnimationController _animationController;
  Animation<double> _translateButton;
  Curve _curve = Curves.easeOut;
  double _fabHeight = 58;
  double menuButtonSize = 55;
  Color menuButtonTheme;
  ColorBloc colorBloc = ColorBloc();

  @override
  initState() {
    _animationController =
    AnimationController(vsync: this, duration: Duration(milliseconds: 600))
      ..addListener(() {
        setState(() {});
      });
    _translateButton = Tween<double>(
      begin: 0.0,
      end: _fabHeight,
    ).animate(CurvedAnimation(
      parent: _animationController,
      curve: Interval(
        0.0,
        1.0,
        curve: _curve,
      ),
    ));
    super.initState();
  }

  @override
  dispose() {
    _animationController.dispose();
    colorBloc.dispose();
    super.dispose();
  }

  animate() {
    if (!isOpened) {
      _animationController.forward();
    } else {
      _animationController.reverse();
    }
    isOpened = !isOpened;
  }

  Widget backgroundColour() {
    return StreamBuilder(
      initialData: Colors.blue,
      stream: colorBloc.colorStream,
      builder: (BuildContext context, snapShot) => Container(
        width: menuButtonSize,
        height: menuButtonSize,
        child: RawMaterialButton(
          shape: CircleBorder(),
          fillColor: Colors.black,
          elevation: 5.0,
          onPressed: (){},
          child: Container(
            height: menuButtonSize - 3,
            width: menuButtonSize - 3,
            decoration: BoxDecoration(
              color: snapShot.data,
              shape: BoxShape.circle,
            ),
            child: Image.asset(
              'lib/images/background_colour.png',
              scale: 4,
            ),
          ),
        ),
      ),
    );
  }

  Widget toggle() {
    return Transform.rotate(
      angle: _animationController.value * (pi * 2),
      child: Container(
        width: menuButtonSize,
        height: menuButtonSize,
        child: RawMaterialButton(
          shape: CircleBorder(),
          fillColor: Colors.black,
          elevation: 5.0,
          onPressed: animate,
          child: SizedBox(
            height: menuButtonSize - 3,
            width: menuButtonSize - 3,
            child: Image.asset('lib/images/ic_launcher.png'),
          ),
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: <Widget> [
        BlocProvider(
          bloc: ColorBloc(),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.start,
            children: [
              Stack(
                children: <Widget>[
                  Transform(
                    transform: Matrix4.translationValues(
                      0,
                      _translateButton.value,
                      0,
                    ),
                    child: backgroundColour(),
                  ),
                  toggle(),
                ],
              ),
            ],
          ),
        ),
        Column(
          mainAxisAlignment: MainAxisAlignment.start,
          children: <Widget>[
            Container(
              height: menuButtonSize,
              width: menuButtonSize,
              child: Opacity(
                opacity: 0.0,
                child: FloatingActionButton(
                  heroTag: null,
                  onPressed: animate,
                ),
              ),
            ),
            SizedBox(
              height: 3.0,
            ),
            Container(
              height: menuButtonSize,
              width: menuButtonSize,
              child: Opacity(
                opacity: 0.0,
                child: FloatingActionButton(
                  heroTag: null,
                  onPressed:  isOpened == true? (){
                    widget?._callback('background');
                  } : () {},
                ),
              ),
            ),
          ],
        ),
      ],
    );
  }
}

singleplayer.dart

singleplayer.dart

import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:ultimate_mtg/dropdownmenu.dart';
import 'package:ultimate_mtg/model/colorBloc.dart';

class SinglePlayerMode extends StatefulWidget {
  @override
  SinglePlayerModeParentState createState() => SinglePlayerModeParentState();
}

class SinglePlayerModeParentState extends State<SinglePlayerMode> {

  ColorBloc colorBloc = ColorBloc();

  @override
  void initState() {
    super.initState();
    SystemChrome.setEnabledSystemUIOverlays([]);
    SystemChrome.setPreferredOrientations([DeviceOrientation.landscapeLeft,]);
    Screen.keepOn(true);
  }

  @override
  dispose() {
    colorBloc.dispose();
    super.dispose();
  }

  _changeColourButton() {
    colorBloc.changeColor();
  }

  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: () => _exitApp(context),
      child: Scaffold(
        body: Container(
          child: Row(
            children: <Widget> [
              FloatingActionButton(
                backgroundColor: Colors.blue,
                heroTag: null,
                onPressed: _changeColourButton,
                child: Text(
                  'change',
                ),
              ),
              dropDownMenu(
                singlePlayerCallbacks: callBacks,
              ),
            ],
          ),
        ),
      ),
    );
  }
}

基本上,这就是我要尝试的方式.

That's basically how I am trying to do it.

推荐答案

我对代码中的注释进行了一些修改.无法对其进行测试以确保其正常工作,因此请尝试一下.

I've made some modifications with comments in the code. Can't test it to be sure it's working, so just try it out.

SinglePlayer.dart

import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:tv_series_jokes/blocs/bloc_provider.dart';
import 'package:ultimate_mtg/dropdownmenu.dart';
import 'package:ultimate_mtg/model/colorBloc.dart';

class SinglePlayerMode extends StatefulWidget {
  @override
  SinglePlayerModeParentState createState() => SinglePlayerModeParentState();
}

class SinglePlayerModeParentState extends State<SinglePlayerMode> {

  ColorBloc colorBloc = ColorBloc(); // our color bloc instance

  @override
  void initState() {
    super.initState();
    SystemChrome.setEnabledSystemUIOverlays([]);
    SystemChrome.setPreferredOrientations([DeviceOrientation.landscapeLeft,]);
    Screen.keepOn(true);
  }

  @override
  dispose() {
    colorBloc.dispose();
    super.dispose();
  }

  _changeColourButton() {
    colorBloc.changeColor();
  }

  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: () => _exitApp(context),
      child: Scaffold(
        body: BlocProvider<ColorBloc>( // DropDownMenu can now access the bloc with this
            bloc: colorBloc,
            child: Container(
          child: Row(
            children: <Widget> [
              FloatingActionButton(
                backgroundColor: Colors.blue,
                heroTag: null,
                onPressed: _changeColourButton,
                child: Text(
                  'change',
                ),
              ),
              dropDownMenu(
                singlePlayerCallbacks: callBacks,
              ),
            ],
          ),
        ),   
        ),
      ),
    );
  }
}  

DropDownMenu.dart

import 'package:flutter/material.dart';
import 'dart:math';
import 'package:ultimate_mtg/model/colorBloc.dart';
import 'package:ultimate_mtg/model/blocprovider.dart';

// ignore: camel_case_types
class dropDownMenu extends StatefulWidget {
  final Function() onPressed;
  final String tooltip;
  final IconData icon;
  final _callback;

  dropDownMenu({Key key, this.onPressed, this.tooltip, this.icon, @required void singlePlayerCallbacks(String callBackType), @required StatefulWidget styleMenu }  ):
      _callback = singlePlayerCallbacks;

  @override
  dropDownMenuState createState() => dropDownMenuState();
}

// ignore: camel_case_types
class dropDownMenuState extends State<dropDownMenu>
    with SingleTickerProviderStateMixin {
  bool isOpened = false;
  AnimationController _animationController;
  Animation<double> _translateButton;
  Curve _curve = Curves.easeOut;
  double _fabHeight = 58;
  double menuButtonSize = 55;
  Color menuButtonTheme;
  ColorBloc colorBloc; // we no longer create the instance here.

  @override
  initState() {
    _animationController =
    AnimationController(vsync: this, duration: Duration(milliseconds: 600))
      ..addListener(() {
        setState(() {});
      });
    _translateButton = Tween<double>(
      begin: 0.0,
      end: _fabHeight,
    ).animate(CurvedAnimation(
      parent: _animationController,
      curve: Interval(
        0.0,
        1.0,
        curve: _curve,
      ),
    ));


    colorBloc = BlocProvider.of<ColorBloc>(context); // Getting the color bloc from the widget tree
    super.initState();
  }

  @override
  dispose() {
    _animationController.dispose();
    super.dispose();
  }

  animate() {
    if (!isOpened) {
      _animationController.forward();
    } else {
      _animationController.reverse();
    }
    isOpened = !isOpened;
  }

  Widget backgroundColour() {
    return StreamBuilder(
      initialData: Colors.blue,
      stream: colorBloc.colorStream,
      builder: (BuildContext context, snapShot) => Container(
        width: menuButtonSize,
        height: menuButtonSize,
        child: RawMaterialButton(
          shape: CircleBorder(),
          fillColor: Colors.black,
          elevation: 5.0,
          onPressed: (){},
          child: Container(
            height: menuButtonSize - 3,
            width: menuButtonSize - 3,
            decoration: BoxDecoration(
              color: snapShot.data,
              shape: BoxShape.circle,
            ),
            child: Image.asset(
              'lib/images/background_colour.png',
              scale: 4,
            ),
          ),
        ),
      ),
    );
  }

  Widget toggle() {
    return Transform.rotate(
      angle: _animationController.value * (pi * 2),
      child: Container(
        width: menuButtonSize,
        height: menuButtonSize,
        child: RawMaterialButton(
          shape: CircleBorder(),
          fillColor: Colors.black,
          elevation: 5.0,
          onPressed: animate,
          child: SizedBox(
            height: menuButtonSize - 3,
            width: menuButtonSize - 3,
            child: Image.asset('lib/images/ic_launcher.png'),
          ),
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {

    return Stack(
      children: <Widget> [
       // Removed the BlocProvider widget here. It wasn't working anything and was creating a separate bloc instance
       // I also see why you tried to make us of the blocprovider in the backgroundColour method and it gave null.Couldn't
       // have worked from that context.
       Column(
            mainAxisAlignment: MainAxisAlignment.start,
            children: [
              Stack(
                children: <Widget>[
                  Transform(
                    transform: Matrix4.translationValues(
                      0,
                      _translateButton.value,
                      0,
                    ),
                    child: backgroundColour(),
                  ),
                  toggle(),
                ],
              ),
            ],
        ),
        Column(
          mainAxisAlignment: MainAxisAlignment.start,
          children: <Widget>[
            Container(
              height: menuButtonSize,
              width: menuButtonSize,
              child: Opacity(
                opacity: 0.0,
                child: FloatingActionButton(
                  heroTag: null,
                  onPressed: animate,
                ),
              ),
            ),
            SizedBox(
              height: 3.0,
            ),
            Container(
              height: menuButtonSize,
              width: menuButtonSize,
              child: Opacity(
                opacity: 0.0,
                child: FloatingActionButton(
                  heroTag: null,
                  onPressed:  isOpened == true? (){
                    widget?._callback('background');
                  } : () {},
                ),
              ),
            ),
          ],
        ),
      ],
    );
  }
}  

这篇关于Bloc流未正确更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆