Flutter - 如何将 Bloc 作为可重用 Widget 中的参数传递?

Dan*_*ral 6 flutter bloc flutter-bloc

我正在构建一个登录页面,并且已经创建了打算用作完全动态 TextField 小部件的内容。

我现在需要创建该小部件的 2 个实例(电子邮件和密码输入)并发送hintText、errorText 的参数,然后发送我的LoginBloc 和验证方法,这些参数对于每个输入当然是不同的。

我的问题是 Dart 不允许我使用小部件接收的块作为类型,因此代码不起作用。

我可以做什么来解决这个问题?或者我完全做错了,有更好的方法吗?

登录页面:

@override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        body: Padding(
          padding: const EdgeInsets.only(
            left: 16,
            right: 16,
          ),
          child: SingleChildScrollView(
            child: Column(
              children: <Widget>[
                Container(
                  margin: EdgeInsets.only(top: 50),
                  child: Text(
                    AppLocalizations.of(context).initiateSession,
                    style: Theme.of(context).textTheme.headline6,
                  ),
                ),
                BlocProvider(
                  create: (context) {
                    return LoginBloc();
                  },
                  child: BlocListener<LoginBloc, LoginState>(
                    listener: (context, state) {
                      if (state.status.isSubmissionFailure) {
                        ScaffoldMessenger.of(context)
                          ..hideCurrentSnackBar()
                          ..showSnackBar(
                            const SnackBar(
                                content: Text('Authentication Failure')),
                          );
                      }
                    },
                    child: Align(
                      alignment: const Alignment(0, -1 / 3),
                      child: Column(
                        mainAxisSize: MainAxisSize.min,
                        children: [
                          TextInput(AppLocalizations.of(context).email, LoginBloc, LoginEmailChanged, getError),
                          TextInput(AppLocalizations.of(context).password, LoginBloc, LoginEmailChanged, getError),
                        ],
                      ),
                    ),
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

自定义文本字段:

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

class TextInput extends StatelessWidget {
  final String hint;
  final Bloc bloc;
  final Function blocEvent;
  final String errorMessage;

  TextInput(this.hint, this.bloc, this.blocEvent, this.errorMessage);

  @override
  Widget build(BuildContext context) {
    return Container(
      margin: EdgeInsets.only(top: 10),
      child: TextField(
        decoration: InputDecoration(
          fillColor: Color(0xfff5f5f5),
          filled: true,
          border: InputBorder.none,
          hintText: hint,
          hintStyle: TextStyle(
            color: Color(0xffb4b4b4),
            fontSize: 18.0,
            fontFamily: 'Helvetica',
            fontWeight: FontWeight.w100,
          ),
          contentPadding: EdgeInsets.symmetric(
            vertical: 22,
            horizontal: 14,
          ),
          errorText: errorMessage,
        ),
        style: Theme.of(context).textTheme.bodyText1,
        cursorColor: Theme.of(context).primaryColor,
        cursorHeight: 20,
        onChanged: (textValue) =>
            context.read<bloc>().add(blocEvent(textValue)), //this is the line where the error occurs, where I use "bloc" as a type.
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

Bip*_*tta 1

您不应该将 bloc 和 blocEvent 作为参数传递给 TextInput 小部件。BlocProvider.of<LoginBloc>()您可以使用或 来从您的子小部件中执行查找,context.read<LoginBloc>()以获取 LoginBloc 的实例。

首先,最好为 EmailInputTextField 和 PasswordInputTextField 有 2 个单独的小部件类。现在您可以管理独立的文本字段。

然后你的块中应该有一些事件处理代码。例如,onEmailChanged()onPasswordChanged()

然后你可以做类似的事情:

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

class EmailInputTextField extends StatelessWidget {

  const EmailInputTextField({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      margin: EdgeInsets.only(top: 10),
      child: BlocBuilder<LoginBloc, LoginState>(
      builder: (context, state) {
        return TextField(
          decoration: InputDecoration(
            fillColor: Color(0xfff5f5f5),
            filled: true,
            border: InputBorder.none,
            hintText: 'Enter your email address',
            hintStyle: TextStyle(
              color: Color(0xffb4b4b4),
              fontSize: 18.0,
              fontFamily: 'Helvetica',
              fontWeight: FontWeight.w100,
            ),
            contentPadding: EdgeInsets.symmetric(
              vertical: 22,
              horizontal: 14,
            ),
            errorText: 'Invalid Email',
          ),
          style: Theme.of(context).textTheme.bodyText1,
          cursorColor: Theme.of(context).primaryColor,
          cursorHeight: 20,
          onChanged: (textValue) =>
              context.read<LoginBloc>().add(EmailChanged(textValue));  // Assuming you have an event class EmailChanged()
      );
     },
    ),
  );
 }
}
Run Code Online (Sandbox Code Playgroud)

还,

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

class PasswordInputTextField extends StatelessWidget {

  const PasswordInputTextField({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      margin: EdgeInsets.only(top: 10),
      child: BlocBuilder<LoginBloc, LoginState>(
      builder: (context, state) {
        return TextField(
          decoration: InputDecoration(
            fillColor: Color(0xfff5f5f5),
            filled: true,
            border: InputBorder.none,
            hintText: 'Enter your password',
            hintStyle: TextStyle(
              color: Color(0xffb4b4b4),
              fontSize: 18.0,
              fontFamily: 'Helvetica',
              fontWeight: FontWeight.w100,
            ),
            contentPadding: EdgeInsets.symmetric(
              vertical: 22,
              horizontal: 14,
            ),
            errorText: 'Short Password',
          ),
          style: Theme.of(context).textTheme.bodyText1,
          cursorColor: Theme.of(context).primaryColor,
          cursorHeight: 20,
          onChanged: (textValue) =>
              context.read<LoginBloc>().add(PasswordChanged(textValue));  // Assuming you have an event class PasswordChanged()
      );
     },
    ),
  );
 }
}
Run Code Online (Sandbox Code Playgroud)