我想使用BLoC合作伙伴授权的应用程序,但是遇到错误:
The following NoSuchMethodError was thrown building AuhtScreen(dirty, state: _AuhtScreenState<dynamic>#00539):
The getter 'blocState' was called on null.
Receiver: null
Tried calling: blocState
在以下情况下会被调用:
在AuhtScreen中
AuthBloc authBloc = BlocProvider.of(context).authBloc; (context = StatefulElement)
在BlocProvider中
static BlocState of(BuildContext context) { (context = StatefulElement)
return (context.inheritFromWidgetOfExactType(BlocProvider) as BlocProvider).blocState; (context = StatefulElement)(NULL)
}
我不明白为什么它不起作用,我正确地完成了所有操作,也许我错过了某些东西或不理解...帮助解决问题!
所有代码:
AuthBloc
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:mifity/models/auht_detail.dart';
import 'package:mifity/models/user.dart';
import 'package:mifity/screens/main_screen.dart';
import 'package:mifity/services/auth_service.dart';
import 'package:rxdart/rxdart.dart';
class AuthBloc {
AuthService authService;
BuildContext _context;
final currentUserSubject = BehaviorSubject<User>.seeded(null);
final emailSubject = BehaviorSubject<String>.seeded('');
final passwordSubject = BehaviorSubject<String>.seeded('');
final loadingSubject = BehaviorSubject<bool>.seeded(false);
final loginSubject = BehaviorSubject<Null>.seeded(null);
//sink
void Function(String) get emailChanged => emailSubject.sink.add;
void Function(String) get passwordChanged => passwordSubject.sink.add;
void Function(BuildContext) get submitLogin => (context) {
this.setContext(context);
loginSubject.add(null);
};
//stream
Stream<User> get currentUser => currentUserSubject.stream;
Stream<String> get emailStream => emailSubject.stream;
Stream<String> get passwordStream => passwordSubject.stream;
Stream<bool> get loading => loadingSubject.stream;
AuthBloc({this.authService}) {
Stream<AuhtDetail> auhtDetailStream = Observable.combineLatest2(
emailStream, passwordStream, (email, password) {
return AuhtDetail(email: email, password: password);
});
Stream<User> loggedIn = Observable(loginSubject.stream)
.withLatestFrom(auhtDetailStream, (_, auhtDetail) {
return auhtDetail;
}).flatMap((auhtDetail) {
return Observable.fromFuture(authService.loginUser(auhtDetail))
.doOnListen(() {
loadingSubject.add(true);
}).doOnDone(() {
loadingSubject.add(false);
});
});
loggedIn.listen((User user) {
currentUserSubject.add(user);
Navigator.push(
_context,
new MaterialPageRoute(builder: (context) => MainScreen()),
);
}, onError: (error) {
Scaffold.of(_context).showSnackBar(new SnackBar(
content: new Text("Username or password incorrect"),
));
});
}
setContext(BuildContext context) {
_context = context;
}
close() {
emailSubject.close();
passwordSubject.close();
loadingSubject.close();
loginSubject.close();
}
}
BlocProvider
import 'package:flutter/material.dart';
import 'package:mifity/blocs/auth_bloc.dart';
import 'package:mifity/services/auth_service.dart';
class BlocProvider extends InheritedWidget {
final blocState = new BlocState(
authBloc: AuthBloc(authService: AuthService()),
);
BlocProvider({Key key, Widget child}) : super(key: key, child: child);
bool updateShouldNotify(_) => true;
static BlocState of(BuildContext context) {
return (context.inheritFromWidgetOfExactType(BlocProvider) as BlocProvider)
.blocState;
}
}
class BlocState {
final AuthBloc authBloc;
BlocState({this.authBloc});
}
AuthService
import 'dart:async';
import 'package:mifity/models/auht_detail.dart';
import 'package:mifity/models/error.dart';
import 'package:mifity/models/user.dart';
class AuthService {
Future<User> loginUser(AuhtDetail detail) async {
await Future.delayed(Duration(seconds: 1)); //simulate network delay
if (detail.email == 'johndoe@acme.com' && detail.password == '1234') {
return User(
id: 1,
name: 'John Doe',
email: 'johndoe@acme.com',
age: 26,
profilePic: 'john_doe.png');
} else {
throw ClientError(message: 'login details incorrect.');
}
}
}
验证者:
class Validator {
String validateEmail(String value) {
if (value.isEmpty) return 'Email Should not be empty';
final RegExp emailRegEx = new RegExp(r'^\w+@[a-zA-Z_]+?\.[a-zA-Z]{2,3}$');
if (!emailRegEx.hasMatch(value)) return 'Your Email is invalid';
return null;
}
String validatePassword(String value) {
if (value.length < 4) return 'Password should be four characters or more';
return null;
}
}
AuhtScreen
import 'package:flutter/material.dart';
import 'package:mifity/blocs/auth_bloc.dart';
import 'package:mifity/blocs/bloc_provider.dart';
import 'package:mifity/helpers/validators.dart';
class AuhtScreen extends StatefulWidget {
@override
_AuhtScreenState createState() => _AuhtScreenState();
}
class _AuhtScreenState<StateClass> extends State<AuhtScreen> {
TextEditingController emailController = TextEditingController();
TextEditingController passwordController = TextEditingController();
Validator validator = new Validator();
final formKey = GlobalKey<FormState>();
DecorationImage backgroundImage = new DecorationImage(
image: new ExactAssetImage('assets/images/bg_image.jpg'),
fit: BoxFit.cover,
);
@override
Widget build(BuildContext context) {
AuthBloc authBloc = BlocProvider.of(context).authBloc;
final Size screenSize = MediaQuery.of(context).size;
return Scaffold(
appBar: AppBar(
title: Text('Login'),
),
body: Builder(builder: (context) {
return SingleChildScrollView(
child: Container(
height: screenSize.height - AppBar().preferredSize.height,
padding: EdgeInsets.all(10.0),
alignment: Alignment.center,
decoration: BoxDecoration(
image: (backgroundImage != null) ? backgroundImage : null),
child: Center(
child: Form(
key: formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextFormField(
style: TextStyle(color: Colors.white),
controller: emailController,
decoration: InputDecoration(
labelText: 'email',
labelStyle: TextStyle(color: Colors.grey)),
validator: validator.validateEmail,
),
TextFormField(
style: TextStyle(color: Colors.white),
controller: passwordController,
decoration: InputDecoration(
labelText: 'password',
labelStyle: TextStyle(color: Colors.grey)),
obscureText: true,
validator: validator.validatePassword,
),
SizedBox(
height: 20.0,
),
StreamBuilder<bool>(
initialData: false,
stream: authBloc.loading,
builder: (context, loadingSnapshot) {
return SizedBox(
width: double.infinity,
child: RaisedButton(
color: Colors.deepOrange,
textColor: Colors.white,
child: Text((loadingSnapshot.data)
? 'Login ...'
: 'Login'),
onPressed: () {
_submit(context, authBloc);
},
),
);
},
),
],
),
),
),
),
);
}));
}
_submit(context, AuthBloc authBloc) {
authBloc.emailChanged(emailController.text);
authBloc.passwordChanged(passwordController.text);
if (formKey.currentState.validate()) {
authBloc.submitLogin(context);
}
}
}
答案 0 :(得分:0)
我是个白痴!)
MyApp:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocProvider(
child: MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new AuhtScreen(),
));
}
}