Bloc体系结构“将吸气剂x调用为null”。

时间:2019-05-05 03:58:47

标签: dart flutter stream bloc

根据文档,我正在尝试使用Bloc Architecture设置子小部件的颜色状态,但这是行不通的。这是我的相关文件:

  

blocProvider.dart

import 'package:flutter/material.dart';

Type _typeOf<T>() => T;

abstract class BlocBase {
  void dispose();
}

class BlocProvider<T extends BlocBase> extends StatefulWidget {
  BlocProvider({
    Key key,
    @required this.child,
    @required this.bloc,
  }) : super(key: key);

  final Widget child;
  final T bloc;

  @override
  _BlocProviderState<T> createState() => _BlocProviderState<T>();

  static T of<T extends BlocBase>(BuildContext context) {
    final type = _typeOf<_BlocProviderInherited<T>>();
    _BlocProviderInherited<T> provider =
        context.ancestorInheritedElementForWidgetOfExactType(type)?.widget;
    return provider?.bloc;
  }
}

class _BlocProviderState<T extends BlocBase> extends State<BlocProvider<T>> {
  @override
  void dispose() {
    widget.bloc?.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return new _BlocProviderInherited<T>(
      bloc: widget.bloc,
      child: widget.child,
    );
  }
}

class _BlocProviderInherited<T> extends InheritedWidget {
  _BlocProviderInherited({
    Key key,
    @required Widget child,
    @required this.bloc,
  }) : super(key: key, child: child);

  final T bloc;

  @override
  bool updateShouldNotify(_BlocProviderInherited oldWidget) => false;
}
  

colorBloc.dart

import 'dart:async';
import 'package:ultimate_mtg/model/blocprovider.dart';
import 'dart:ui';
import 'dart:math';


class ColorBloc extends BlocBase {
// streams of Color
  StreamController streamListController = StreamController<Color>.broadcast();
// sink
  Sink get colorSink => streamListController.sink;
// stream
  Stream<Color> get colorStream => streamListController.stream;

// function to change the color
  changeColor() {
    colorSink.add(getRandomColor());
  }

  @override
  dispose() {
    streamListController.close();
  }
}



// Random Colour generator
Color getRandomColor() {
  Random _random = Random();
  return Color.fromARGB(
    _random.nextInt(256),
    _random.nextInt(256),
    _random.nextInt(256),
    _random.nextInt(256),
  );
}

还有我的孩子小部件:

  

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();
    super.dispose();
  }

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

  Widget backgroundColour() {
    colorBloc = BlocProvider.of(context);
    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');
                  } : () {},
                ),
              ),
            ),
          ],
        ),
      ],
    );
  }
}

我遇到的错误是在backgroundColour()小部件中:

  Widget backgroundColour() {
    colorBloc = BlocProvider.of(context);
    return StreamBuilder(
      initialData: Colors.blue,
      stream: colorBloc.colorStream,

在显示>流的行上:colorBloc.colorStream,

这是日志中的特定错误:

I/flutter (18865): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
I/flutter (18865): The following NoSuchMethodError was thrown building dropDownMenu(dirty, state:
I/flutter (18865): dropDownMenuState#7edb3(ticker inactive)):
I/flutter (18865): The getter 'colorStream' was called on null.
I/flutter (18865): Receiver: null
I/flutter (18865): Tried calling: colorStream

我已尽可能严格地遵循文档,但是我看不到他们初始化此流的任何地方,或任何具有这种性质的东西。我真的不了解此错误或如何解决。有人对流有任何经验吗?

1 个答案:

答案 0 :(得分:1)

调用'of'方法时,您没有传递BlocBase子类。

使用colorBloc = BlocProvider.of<ColorBloc>(context);
代替
colorBloc = BlocProvider.of(context);

编辑:
再次查看代码,因为ColorBloc位于当前类中而不位于小部件树中,所以您不需要该行。只需删除该行即可使用上面的ColorBloc实例。