收听流提供程序中的更改并在Flutter中调用某些方法

时间:2020-10-06 18:52:16

标签: flutter dart flutter-layout provider flutter-provider

我想听一些关于流事件的更改。现在,我使用提供程序的StreamProvider.value()来完成此操作。这是一个API调用。现在,我想要的是,如果流的事件进入加载状态,我要显示正在加载,如果有任何失败,我想调用失败方法。如果成功,那么我想调用成功方法。

我创建了一个单独的窗口小部件按钮,它是Consumer,可以根据流的事件进行更改。我已经在消费者的builder方法内添加了SchedulerBinding.instance.addPostFrameCallback(),但是随着小部件的重建它被调用了很多次,并触发了最后一个事件,这是不希望的。

所以我的问题是流的事件更改,如何调用这些方法或显示Toast并更新UI?

ConsumerButtonWithProgress

class ConsumerButtonWithProgress<T> extends StatelessWidget {
  final void Function(BuildContext context) onTap;
  final void Function(T result) onSuccess;
  final void Function() onError;
  final void Function() onNoInternet;

  ConsumerButtonWithProgress(
    this.onTap,
    this.onSuccess, {
    this.onError,
    this.onNoInternet,
  }) : assert(T != dynamic);

  @override
  Widget build(BuildContext context) {
    return Consumer<APIResult<T>>(
      builder: (BuildContext context, APIResult<T> value, Widget child) {
        SchedulerBinding.instance.addPostFrameCallback((_) {
          if (value != null) {
            if (value.apiResultType == APIResultType.NO_INTERNET) {
              showSnackBar(context, value.message);
              if (onNoInternet != null) Function.apply(onNoInternet, []);
            } else if (value.apiResultType == APIResultType.FAILURE) {
              showSnackBar(context, value.message);
              if (onError != null) Function.apply(onError, []);
            } else if (value.apiResultType == APIResultType.SUCCESS) {
              showSnackBar(context, value.message);
              Function.apply(onSuccess, [value.data]);
            }
          }
        });
        return Container(
          width: MediaQuery.of(context).size.width,
          height: Dimensions.h50,
          child: OutlineButton(
              color: LocalColors.PRIMARY_COLOR,
              textColor: LocalColors.PRIMARY_COLOR,
              disabledBorderColor: LocalColors.PRIMARY_COLOR,
              highlightedBorderColor: LocalColors.PRIMARY_COLOR,
              borderSide: BorderSide(color: LocalColors.PRIMARY_COLOR),
              child: APIResult.isLoading(value)
                  ? Row(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                        SizedBox(
                            width: Dimensions.h25,
                            height: Dimensions.h25,
                            child: CircularProgressIndicator(
                              strokeWidth: 3,
                            )),
                      ],
                    )
                  : Text(
                      "Button",
                      style: TextStyle(
                        fontSize: Dimensions.sp15,
                        fontWeight: FontAsset.DEMI_BOLD,
                      ),
                    ),
              onPressed: () {
                if (onTap != null &&
                    (value == null ||
                        value.apiResultType != APIResultType.LOADING))
                  Function.apply(onTap, [context]);
              }),
        );
      },
    );
  }
}

这就是我在小部件中使用该按钮的方式

class ForgotPasswordScreen extends StatefulWidget {
  @override
  _ForgotPasswordScreenState createState() => _ForgotPasswordScreenState();
}

class _ForgotPasswordScreenState extends State<ForgotPasswordScreen> {
  ForgotPasswordProvider _forgotPasswordProvider;

  @override
  void initState() {
    super.initState();
    _forgotPasswordProvider = ForgotPasswordProvider();
  }

  @override
  Widget build(BuildContext mainContext) {
    return Scaffold(body: Builder(builder: (BuildContext context) {
      return StreamProvider.value(
        lazy: true,
        value: _forgotPasswordProvider.forgotPasswordStream,
        child: ConsumerButtonWithProgress<SignInResponseEntity>(
          _onSendLinkClick,
              (result) {},
        ),
      );
    }));
  }

  void _onSendLinkClick(BuildContext context) {
    if (_isDataValid(context)) {
      _forgotPasswordProvider.callForgotPasswordAPI();
    }
  }
}

那么,在流的事件更新后以及在更新UI后,有什么方法可以调用方法并从通用小部件中显示吐司?就像在SchedulerBinding.instance.addPostFrameCallback()块中执行代码一样。

0 个答案:

没有答案