如何将 Stream<String> 值作为参数传递给在 bloc 文件 FLUTTER 中创建的函数
How to pass Stream<String> values as parameters to a function created in a bloc file FLUTTER
我有一个登录 bloc 文件,我在其中创建了 2 个流用户名和密码
class LoginBloc {
LoginRepository _loginRepository = new LoginRepository();
StreamController _loginController = StreamController<Response<LoginModel>>();
//declare streams
final _userName = BehaviorSubject<String>();
final _password = BehaviorSubject<String>();
//get data from streams
StreamSink<Response<LoginModel>> get loginControllerSink =>
_loginController.sink;
Stream<String> get loginUserName => _userName.stream;
Stream<String> get loginPassword => _password.stream;
Stream<bool> get submitLoginForm =>
Rx.combineLatest2(loginUserName, loginPassword, (a, b) => true);
Function(String) get changeLoginUserName => _userName.sink.add;
Function(String) get changeLoginPassword => _password.sink.add;
//dispose
dispose() {
_userName.close();
_password.close();
}
//functions
login(email, password, context) async {
try {
LoginModel data = await _loginRepository.loginIntoSystem(email, password);
loginControllerSink.add(Response.completed(data));
Navigator.pushNamed(context, '/dashboard');
} catch (e) {
loginControllerSink.add(Response.error(e.toString()));
print(e);
}
}
}
这是login.dart
class Login extends StatefulWidget {
@override
_LoginState createState() => _LoginState();
}
class _LoginState extends State<Login> {
bool _passwordVisible = false;
@override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
final LoginBloc bloc = LoginProvider.of(context);
return Scaffold(
backgroundColor: Colors.white,
body: SingleChildScrollView(
child: SafeArea(
child: Center(
child:
Column(
children: <Widget>[
SizedBox(height: size.height*0.05),
Icon(
Icons.track_changes,
size: size.width*0.06,
),
SizedBox(height: size.height*0.02),
Text('Login',
style: TextStyle(
color: Color(0xff005D6C),
fontSize: size.width*0.02,
fontWeight: FontWeight.bold,
fontStyle: FontStyle.italic)),
SizedBox(height: size.height*0.04),
Container(
width: size.width * 0.2,
padding: EdgeInsets.only(bottom: 20.0),
child: StreamBuilder<String>(
stream: bloc.loginUserName,
builder: (context, snapshot) {
return TextField(
onChanged: bloc.changeLoginUserName,
decoration: new InputDecoration(
contentPadding: EdgeInsets.symmetric(vertical: 0, horizontal: 15.0),
border: new OutlineInputBorder(
borderSide: const BorderSide(
width: 2.0, style: BorderStyle.solid),
borderRadius: BorderRadius.circular(50.0)),
focusedBorder: OutlineInputBorder(
borderSide: const BorderSide(
color: Colors.grey, width: 2.0),
borderRadius: BorderRadius.circular(50.0),
),
hintText: 'User Name',
hintStyle: new TextStyle(
color: Colors.grey,
fontWeight: FontWeight.bold),
suffixIcon: const Icon(
Icons.person,
size: 30.0,
color: Colors.grey,
),
errorText: snapshot.error),
);
}),
),
Container(
width: size.width * 0.2,
padding: EdgeInsets.only(bottom: 20.0),
child: StreamBuilder<String>(
stream: bloc.loginPassword,
builder: (context, snapshot) {
return TextField(
onChanged: bloc.changeLoginPassword,
obscureText: !_passwordVisible,
maxLength: 20,
decoration: new InputDecoration(
contentPadding: EdgeInsets.symmetric(vertical: 0, horizontal: 15.0),
border: new OutlineInputBorder(
borderSide: const BorderSide(
width: 2.0, style: BorderStyle.solid),
borderRadius: BorderRadius.circular(50.0)),
focusedBorder: OutlineInputBorder(
borderSide: const BorderSide(
color: Colors.grey, width: 2.0),
borderRadius: BorderRadius.circular(50.0),
),
hintText: 'Password',
hintStyle: new TextStyle(
color: Colors.grey,
fontWeight: FontWeight.bold),
prefixIcon: const Icon(
Icons.lock,
size: 30.0,
color: Colors.grey,
),
suffixIcon: IconButton(
icon: Icon(
// Based on passwordVisible state choose the icon
_passwordVisible
? Icons.visibility
: Icons.visibility_off,
color: Colors.grey,
),
onPressed: () {
setState(() {
_passwordVisible = !_passwordVisible;
});
},
),
errorText: snapshot.error),
);
}),
),
Container(
width: size.width * 0.2,
child: ClipRRect(
borderRadius: BorderRadius.circular(29),
child: StreamBuilder<bool>(
stream: bloc.submitLoginForm,
builder: (context, snapshot){
return FlatButton(
color: Color(0XFFEFEFEF),
textColor: primaryColor,
disabledColor: Colors.grey,
disabledTextColor: Colors.black,
padding: EdgeInsets.symmetric(
vertical: 12.0, horizontal: 10.0),
onPressed: () => snapshot.hasError ? null : bloc.login(bloc.loginUserName, bloc.loginPassword, context) ,
child: Text(
"Login",
style: TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.bold,
fontStyle: FontStyle.italic),
),
);
},
),
),
)
],
)
),
),
),
);
}
}
我在单击登录按钮时调用登录函数,并将用户名、密码和上下文作为参数传递。但是点击它给出 "预期类型 'String' 的值,但得到类型 'BehaviorSubject'" 中的一个值
添加了 loginIntoSystem:
Future<LoginModel> loginIntoSystem(String email, String password)
async {
dynamic body = {
'email': email,
'password': password
};
final response = await _provider.post("/login", body);
return LoginModel.fromJson(response);
}
有没有办法将 BehaviorSubject 转换为 String ?
你是对的。我错了,行为主体有一个 属性 value
那个行为主体的 returns 值。您可以使用它从您的行为主体中获取电子邮件和密码。此外,由于您的 bloc 文件已经可以访问这些变量,因此您不必将它们作为 onPressed 函数的参数传递。
login(context) async {
final email = _userName.value;
final password = _password.value;
try {
LoginModel data = await _loginRepository.loginIntoSystem(email, password);
loginControllerSink.add(Response.completed(data));
Navigator.pushNamed(context, '/dashboard');
} catch (e) {
loginControllerSink.add(Response.error(e.toString()));
print(e);
}
}
我找到了解决方案。
通过使用值 属性,我能够获取这些值。
final fEmail = _email.value;
final fPassword = _password.value;
感谢大家花时间发布答案。
我有一个登录 bloc 文件,我在其中创建了 2 个流用户名和密码
class LoginBloc {
LoginRepository _loginRepository = new LoginRepository();
StreamController _loginController = StreamController<Response<LoginModel>>();
//declare streams
final _userName = BehaviorSubject<String>();
final _password = BehaviorSubject<String>();
//get data from streams
StreamSink<Response<LoginModel>> get loginControllerSink =>
_loginController.sink;
Stream<String> get loginUserName => _userName.stream;
Stream<String> get loginPassword => _password.stream;
Stream<bool> get submitLoginForm =>
Rx.combineLatest2(loginUserName, loginPassword, (a, b) => true);
Function(String) get changeLoginUserName => _userName.sink.add;
Function(String) get changeLoginPassword => _password.sink.add;
//dispose
dispose() {
_userName.close();
_password.close();
}
//functions
login(email, password, context) async {
try {
LoginModel data = await _loginRepository.loginIntoSystem(email, password);
loginControllerSink.add(Response.completed(data));
Navigator.pushNamed(context, '/dashboard');
} catch (e) {
loginControllerSink.add(Response.error(e.toString()));
print(e);
}
}
}
这是login.dart
class Login extends StatefulWidget {
@override
_LoginState createState() => _LoginState();
}
class _LoginState extends State<Login> {
bool _passwordVisible = false;
@override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
final LoginBloc bloc = LoginProvider.of(context);
return Scaffold(
backgroundColor: Colors.white,
body: SingleChildScrollView(
child: SafeArea(
child: Center(
child:
Column(
children: <Widget>[
SizedBox(height: size.height*0.05),
Icon(
Icons.track_changes,
size: size.width*0.06,
),
SizedBox(height: size.height*0.02),
Text('Login',
style: TextStyle(
color: Color(0xff005D6C),
fontSize: size.width*0.02,
fontWeight: FontWeight.bold,
fontStyle: FontStyle.italic)),
SizedBox(height: size.height*0.04),
Container(
width: size.width * 0.2,
padding: EdgeInsets.only(bottom: 20.0),
child: StreamBuilder<String>(
stream: bloc.loginUserName,
builder: (context, snapshot) {
return TextField(
onChanged: bloc.changeLoginUserName,
decoration: new InputDecoration(
contentPadding: EdgeInsets.symmetric(vertical: 0, horizontal: 15.0),
border: new OutlineInputBorder(
borderSide: const BorderSide(
width: 2.0, style: BorderStyle.solid),
borderRadius: BorderRadius.circular(50.0)),
focusedBorder: OutlineInputBorder(
borderSide: const BorderSide(
color: Colors.grey, width: 2.0),
borderRadius: BorderRadius.circular(50.0),
),
hintText: 'User Name',
hintStyle: new TextStyle(
color: Colors.grey,
fontWeight: FontWeight.bold),
suffixIcon: const Icon(
Icons.person,
size: 30.0,
color: Colors.grey,
),
errorText: snapshot.error),
);
}),
),
Container(
width: size.width * 0.2,
padding: EdgeInsets.only(bottom: 20.0),
child: StreamBuilder<String>(
stream: bloc.loginPassword,
builder: (context, snapshot) {
return TextField(
onChanged: bloc.changeLoginPassword,
obscureText: !_passwordVisible,
maxLength: 20,
decoration: new InputDecoration(
contentPadding: EdgeInsets.symmetric(vertical: 0, horizontal: 15.0),
border: new OutlineInputBorder(
borderSide: const BorderSide(
width: 2.0, style: BorderStyle.solid),
borderRadius: BorderRadius.circular(50.0)),
focusedBorder: OutlineInputBorder(
borderSide: const BorderSide(
color: Colors.grey, width: 2.0),
borderRadius: BorderRadius.circular(50.0),
),
hintText: 'Password',
hintStyle: new TextStyle(
color: Colors.grey,
fontWeight: FontWeight.bold),
prefixIcon: const Icon(
Icons.lock,
size: 30.0,
color: Colors.grey,
),
suffixIcon: IconButton(
icon: Icon(
// Based on passwordVisible state choose the icon
_passwordVisible
? Icons.visibility
: Icons.visibility_off,
color: Colors.grey,
),
onPressed: () {
setState(() {
_passwordVisible = !_passwordVisible;
});
},
),
errorText: snapshot.error),
);
}),
),
Container(
width: size.width * 0.2,
child: ClipRRect(
borderRadius: BorderRadius.circular(29),
child: StreamBuilder<bool>(
stream: bloc.submitLoginForm,
builder: (context, snapshot){
return FlatButton(
color: Color(0XFFEFEFEF),
textColor: primaryColor,
disabledColor: Colors.grey,
disabledTextColor: Colors.black,
padding: EdgeInsets.symmetric(
vertical: 12.0, horizontal: 10.0),
onPressed: () => snapshot.hasError ? null : bloc.login(bloc.loginUserName, bloc.loginPassword, context) ,
child: Text(
"Login",
style: TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.bold,
fontStyle: FontStyle.italic),
),
);
},
),
),
)
],
)
),
),
),
);
}
}
我在单击登录按钮时调用登录函数,并将用户名、密码和上下文作为参数传递。但是点击它给出 "预期类型 'String' 的值,但得到类型 'BehaviorSubject'" 中的一个值
添加了 loginIntoSystem:
Future<LoginModel> loginIntoSystem(String email, String password)
async {
dynamic body = {
'email': email,
'password': password
};
final response = await _provider.post("/login", body);
return LoginModel.fromJson(response);
}
有没有办法将 BehaviorSubject 转换为 String ?
你是对的。我错了,行为主体有一个 属性 value
那个行为主体的 returns 值。您可以使用它从您的行为主体中获取电子邮件和密码。此外,由于您的 bloc 文件已经可以访问这些变量,因此您不必将它们作为 onPressed 函数的参数传递。
login(context) async {
final email = _userName.value;
final password = _password.value;
try {
LoginModel data = await _loginRepository.loginIntoSystem(email, password);
loginControllerSink.add(Response.completed(data));
Navigator.pushNamed(context, '/dashboard');
} catch (e) {
loginControllerSink.add(Response.error(e.toString()));
print(e);
}
}
我找到了解决方案。
通过使用值 属性,我能够获取这些值。
final fEmail = _email.value;
final fPassword = _password.value;
感谢大家花时间发布答案。