Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/dart/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Flutter 颤振:子块正在初始化,但数据尚未存储在共享_首选项中_Flutter_Dart_Bloc_Flutter Navigation - Fatal编程技术网

Flutter 颤振:子块正在初始化,但数据尚未存储在共享_首选项中

Flutter 颤振:子块正在初始化,但数据尚未存储在共享_首选项中,flutter,dart,bloc,flutter-navigation,Flutter,Dart,Bloc,Flutter Navigation,我用于我的应用程序jwt身份验证。我有一个带有bloc模式的主页,它选择页面将其加载到屏幕上(LoginScreen或AppScreen)。LoginScreen有自己的集团模式,也有AppScreen。 当我写login和password并单击login时,LoginEvent被调度,它向web服务发送请求,并使用jwt令牌获得响应,jwt令牌将存储在共享首选项中,但同时AppScreen使用他的bloc呈现,此时AppScreen的bloc正在发送数据请求(需要jwt令牌),但返回null,

我用于我的应用程序jwt身份验证。我有一个带有bloc模式的主页,它选择页面将其加载到屏幕上(LoginScreen或AppScreen)。LoginScreen有自己的集团模式,也有AppScreen。 当我写login和password并单击login时,LoginEvent被调度,它向web服务发送请求,并使用jwt令牌获得响应,jwt令牌将存储在共享首选项中,但同时AppScreen使用他的bloc呈现,此时AppScreen的bloc正在发送数据请求(需要jwt令牌),但返回null,因为jwt令牌尚未存储。我发现一种工作方式并不优雅,我也可以使用延迟,但这不是正确的方式

AppScreen的解决方法:

@override
  void initState() {
    super.initState();
    _bloc = BottomNavigationBloc(workoutTypeRepository: WorkoutTypeRepository());
    _bloc.add(AppScreenLunched());
    _bloc.add(AppScreenLunched());
  }
class AppScreen extends StatefulWidget {
  @override
  _AppScreenState createState() => _AppScreenState();
}

class _AppScreenState extends State<AppScreen> {
  BottomNavigationBloc _bloc;

  @override
  void initState() {
    super.initState();
    _bloc = BottomNavigationBloc(workoutTypeRepository: WorkoutTypeRepository());
    _bloc.add(AppScreenLunched());
    _bloc.add(AppScreenLunched());
  }


  @override
  void dispose() {
    super.dispose();
    _bloc.close();
  }

  @override
  Widget build(BuildContext context) {
    return BlocProvider<BottomNavigationBloc>(
      create: (_) => _bloc,
      child: BlocBuilder(
        bloc: _bloc,
        builder: (BuildContext context, BottomNavigationState state) {
          return Scaffold(
            appBar: AppBar(
              title: Text('TEST'),
            ),
            body: _blocBuilder(context, state),
            bottomNavigationBar: BottomActionBar(),
          );
        },
      ),
    );
  }

  Widget _blocBuilder(BuildContext context, BottomNavigationState state) {
    if (state is PageLoading) {
      return Center(child: CircularProgressIndicator());
    } else if (state is HomePageLoaded) {
      return HomePage(workoutTypes: state.workoutTypes);
    } else if (state is SearchPageLoaded) {
      return Center(child: Text("SearchPage"));
      // return SearchPage();
    } else if (state is WorkoutPageLoaded) {
//      return Center(child: Text("WorkoutPage"));
       return WorkoutPage();
    } else if (state is FavoritePageLoaded) {
      return Center(child: Text("FavoritePage"));
      // return SearchPage();
    } else if (state is ProfilePageLoaded) {
      return Center(child: Text("ProfilePage"));
      // return ProfilePage();
    }
    return Container();
  }
}
如果我离开
\u bloc.add(appscreenlunted())数据无法加载到主页,因为它从web服务接收空值

如果我离开

_bloc.add(AppScreenLunched()); 
_bloc.add(AppScreenLunched()); 
首先,添加数据为空

通过第二次
add
我最终得到了数据,这些数据随bloc一起提供到主页上

有什么办法吗

开始屏幕:

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  AuthBloc _authBloc;
  LoginRepository _loginRepository;

  @override
  void initState() {
    super.initState();
    _loginRepository = LoginRepository();
    _authBloc = AuthBloc(loginRepository: _loginRepository);
    _authBloc.add(AppStarted());
  }


  @override
  void dispose() {
    super.dispose();
    _authBloc.close();
  }

  @override
  Widget build(BuildContext context) {
    return BlocProvider<AuthBloc>(
        create: (_) => _authBloc,
        child: MaterialApp(
            title: 'TEST',
            theme: ThemeData(
              primarySwatch: Colors.blue,
            ),
            home: BlocBuilder(
                bloc: _authBloc,
                builder: (BuildContext context, AuthState state) {
                  if (state is AuthUninitialized) {
                    return LoginPage(loginRepository: _loginRepository);
                  } else if (state is AuthAuthenticated) {
                    return AppScreen();
                  } else if (state is AuthUnauthenticated) {
                    return LoginPage(loginRepository: _loginRepository);
                  } else if (state is AuthLoading) {
                    return LoadingIndicator();
                  }
                  return LoginPage(loginRepository: _loginRepository);
                }
            )
        )
    );
  }
}
类MyApp扩展StatefulWidget{
@凌驾
_MyAppState createState()=>\u MyAppState();
}
类MyAppState扩展了状态{
AuthBloc\u AuthBloc;
LoginRepository\u LoginRepository;
@凌驾
void initState(){
super.initState();
_loginRepository=loginRepository();
_authBloc=authBloc(loginRepository:_loginRepository);
_add(AppStarted());
}
@凌驾
无效处置(){
super.dispose();
_authBloc.close();
}
@凌驾
小部件构建(构建上下文){
返回BlocProvider(
创建:()=>authBloc,
孩子:MaterialApp(
标题:"测试",,
主题:主题数据(
主样本:颜色。蓝色,
),
主页:BlocBuilder(
集团:_authBloc,
生成器:(BuildContext上下文,AuthState){
如果(状态未初始化){
返回登录页面(loginRepository:\u loginRepository);
}else if(状态已通过身份验证){
返回AppScreen();
}else if(状态为未经身份验证){
返回登录页面(loginRepository:\u loginRepository);
}else if(状态为AuthLoading){
返回LoadingIndicator();
}
返回登录页面(loginRepository:\u loginRepository);
}
)
)
);
}
}
登录筛选(部分):

classloginform扩展StatefulWidget{
@凌驾
_LoginFormState createState()=>\u LoginFormState();
}
类_LoginFormState扩展状态{
final _emailController=TextEditingController();
final _passwordController=TextEditingController();
final registerRepository=registerRepository();
LoginBloc _LoginBloc;
@凌驾
void initState(){
super.initState();
_loginBloc=BlocProvider.of(上下文);
}
@凌驾
无效处置(){
super.dispose();
_loginBloc.close();
}
@凌驾
小部件构建(构建上下文){
_onLoginButtonPressed(){
_loginBloc.add(LoginButtonPressed(
电子邮件:_emailController.text,
密码:_passwordController.text,
));
}
应用屏幕:

@override
  void initState() {
    super.initState();
    _bloc = BottomNavigationBloc(workoutTypeRepository: WorkoutTypeRepository());
    _bloc.add(AppScreenLunched());
    _bloc.add(AppScreenLunched());
  }
class AppScreen extends StatefulWidget {
  @override
  _AppScreenState createState() => _AppScreenState();
}

class _AppScreenState extends State<AppScreen> {
  BottomNavigationBloc _bloc;

  @override
  void initState() {
    super.initState();
    _bloc = BottomNavigationBloc(workoutTypeRepository: WorkoutTypeRepository());
    _bloc.add(AppScreenLunched());
    _bloc.add(AppScreenLunched());
  }


  @override
  void dispose() {
    super.dispose();
    _bloc.close();
  }

  @override
  Widget build(BuildContext context) {
    return BlocProvider<BottomNavigationBloc>(
      create: (_) => _bloc,
      child: BlocBuilder(
        bloc: _bloc,
        builder: (BuildContext context, BottomNavigationState state) {
          return Scaffold(
            appBar: AppBar(
              title: Text('TEST'),
            ),
            body: _blocBuilder(context, state),
            bottomNavigationBar: BottomActionBar(),
          );
        },
      ),
    );
  }

  Widget _blocBuilder(BuildContext context, BottomNavigationState state) {
    if (state is PageLoading) {
      return Center(child: CircularProgressIndicator());
    } else if (state is HomePageLoaded) {
      return HomePage(workoutTypes: state.workoutTypes);
    } else if (state is SearchPageLoaded) {
      return Center(child: Text("SearchPage"));
      // return SearchPage();
    } else if (state is WorkoutPageLoaded) {
//      return Center(child: Text("WorkoutPage"));
       return WorkoutPage();
    } else if (state is FavoritePageLoaded) {
      return Center(child: Text("FavoritePage"));
      // return SearchPage();
    } else if (state is ProfilePageLoaded) {
      return Center(child: Text("ProfilePage"));
      // return ProfilePage();
    }
    return Container();
  }
}
class AppScreen扩展StatefulWidget{
@凌驾
_AppScreenState createState()=>\u AppScreenState();
}
类_AppScreenState扩展状态{
底部导航集团(bloc);;
@凌驾
void initState(){
super.initState();
_bloc=BottomNavigationBloc(workoutTypeRepository:workoutTypeRepository());
_bloc.add(appscreenlunted());
_bloc.add(appscreenlunted());
}
@凌驾
无效处置(){
super.dispose();
_bloc.close();
}
@凌驾
小部件构建(构建上下文){
返回BlocProvider(
创建:(),
孩子:BlocBuilder(
集团:集团,
生成器:(BuildContext上下文,底部导航状态){
返回脚手架(
appBar:appBar(
标题:文本(“测试”),
),
正文:_blocBuilder(上下文、状态),
bottomNavigationBar:BottomActionBar(),
);
},
),
);
}
小部件\u blocBuilder(构建上下文上下文,底部导航状态){
如果(状态为页面加载){
返回中心(子项:CircularProgressIndicator());
}else if(状态为HomePageLoaded){
返回主页(workoutTypes:state.workoutTypes);
}else if(状态为SearchPageLoaded){
返回中心(子:文本(“搜索页面”);
//返回SearchPage();
}else if(状态为WorkoutPageLoaded){
//返回中心(子项:文本(“WorkoutPage”);
返回WorkoutPage();
}else if(状态为FavoritePageLoaded){
返回中心(子项:文本(“FavoritePage”);
//返回SearchPage();
}else if(状态为ProfilePageLoaded){
返回中心(子:文本(“ProfilePage”);
//返回ProfilePage();
}
返回容器();
}
}
AuthBloc:

class AuthBloc extends Bloc<AuthEvent, AuthState> {
  final LoginRepository loginRepository;

  AuthBloc({@required this.loginRepository}) : assert(loginRepository != null);

  @override
  AuthState get initialState => AuthUninitialized();

  @override
  Stream<AuthState> mapEventToState(
    AuthEvent event,
  ) async* {
    if (event is AppStarted) {
      final bool hasToken = await loginRepository.hasToken();

      if (hasToken) {
        yield AuthAuthenticated();
      } else {
        yield AuthUnauthenticated();
      }
    }

    if (event is LoggedIn) {
      final bool hasToken = await loginRepository.hasToken();

      if (hasToken) {
        yield AuthAuthenticated();
      } else {
        yield AuthUnauthenticated();
      }
    }

    if (event is LoggedOut) {
      yield AuthLoading();
      await loginRepository.deleteToken();
      yield AuthUnauthenticated();
    }
  }
}
class AuthBloc extends Bloc<AuthEvent, AuthState> {
  final LoginRepository loginRepository;

  AuthBloc({@required this.loginRepository}) : assert(loginRepository != null);

  @override
  AuthState get initialState => AuthUninitialized();

  @override
  Stream<AuthState> mapEventToState(
    AuthEvent event,
  ) async* {
    if (event is AppStarted) {
      final bool hasToken = await loginRepository.hasToken();

      if (hasToken) {
        yield AuthAuthenticated();
      } else {
        yield AuthUnauthenticated();
      }
    }

    if (event is LoggedIn) {
      final bool hasToken = await loginRepository.hasToken();

      if (hasToken) {
        yield AuthAuthenticated();
      } else {
        yield AuthUnauthenticated();
      }
    }

    if (event is LoggedOut) {
      yield AuthLoading();
      await loginRepository.deleteToken();
      yield AuthUnauthenticated();
    }
  }
}
class AuthBloc扩展了Bloc{
最终登录回复登录回复;
AuthBloc({@required this.loginRepository}):断言(loginRepository!=null);
@凌驾
AuthState get initialState=>AuthUninitialized();
@凌驾
流映射事件状态(
AuthEvent事件,
)异步*{
如果(事件已启动){
final bool hasToken=等待登录repository.hasToken();
如果(hasToken){
屈服强度();
}否则{
生成未经身份验证的();
}
}
if(事件为LoggedIn){
final bool hasToken=等待登录repository.hasToken();
如果(hasToken){
屈服强度();
}否则{
生成未经身份验证的();
}
}
如果(事件为LoggedOut){
屈服载荷();
wait loginRepository.deletetetok
class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  AuthBloc _authBloc;
  LoginRepository _loginRepository;

  @override
  void initState() {
    super.initState();
    _loginRepository = LoginRepository();
    _authBloc = AuthBloc(loginRepository: _loginRepository);
    _authBloc.add(AppStarted());
  }


  @override
  void dispose() {
    super.dispose();
    _authBloc.close();
  }

  @override
  Widget build(BuildContext context) {
    return BlocProvider<AuthBloc>(
        create: (context) => _authBloc,
        child: MaterialApp(
            title: 'TEST',
            theme: ThemeData(
              primarySwatch: Colors.blue,
            ),
            home: BlocBuilder(
                bloc: _authBloc,
                builder: (BuildContext context, AuthState state) {
                  if (state is AuthUninitialized) {
                    return LoadingIndicator();
//                    return LoginPage(loginRepository: _loginRepository);
                  } else if (state is AuthAuthenticated) {
                    return AppScreen();
                  } else if (state is AuthUnauthenticated) {
                    return LoginPage(loginRepository: _loginRepository);
                  } else if (state is AuthLoading) {
                    return LoadingIndicator();
                  }
                  return LoginPage(loginRepository: _loginRepository);
                }
            )
        )
    );
  }
}
class LoginPage extends StatelessWidget {
  final LoginRepository loginRepository;

  LoginPage({
    Key key,
    @required this.loginRepository
  }) : assert(loginRepository != null), super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: BlocProvider(
          create: (context) {
            return LoginBloc(
              loginRepository: loginRepository,
              authBloc: BlocProvider.of<AuthBloc>(context)
            );
          },
          child: Stack(
            children: <Widget>[
              new Container(
                  decoration: BoxDecoration(
                      image: backgroundImage
                  )
              ),
              new Center(
                child: SingleChildScrollView(
                  child: Column(
                      children: <Widget>[
                        LoginForm()
                      ]
                  ),
                ),
              )
            ],
          ),
        )
    );
  }
}
class AuthBloc extends Bloc<AuthEvent, AuthState> {
  final LoginRepository loginRepository;

  AuthBloc({@required this.loginRepository}) : assert(loginRepository != null);

  @override
  AuthState get initialState => AuthUninitialized();

  @override
  Stream<AuthState> mapEventToState(
    AuthEvent event,
  ) async* {
    if (event is AppStarted) {
      final bool hasToken = await loginRepository.hasToken();

      if (hasToken) {
        yield AuthAuthenticated();
      } else {
        yield AuthUnauthenticated();
      }
    }

    if (event is LoggedIn) {
      final bool hasToken = await loginRepository.hasToken();

      if (hasToken) {
        yield AuthAuthenticated();
      } else {
        yield AuthUnauthenticated();
      }
    }

    if (event is LoggedOut) {
      yield AuthLoading();
      await loginRepository.deleteToken();
      yield AuthUnauthenticated();
    }
  }
}
class LoginBloc extends Bloc<LoginEvent, LoginState> {
  final LoginRepository loginRepository;
  final AuthBloc authBloc;

  LoginBloc({
    @required this.loginRepository,
    @required this.authBloc,
  })  : assert(loginRepository != null),
        assert(authBloc != null);

  LoginState get initialState => LoginInitial();

  @override
  Stream<LoginState> mapEventToState(LoginEvent event) async* {
    if (event is LoginButtonPressed) {
      yield LoginLoading();

      try {
        await loginRepository.authenticate(
          email: event.email,
          password: event.password,
        );
        authBloc.add(LoggedIn());
        yield LoginInitial();
      } catch (error) {
        yield LoginFailure(error: error.toString());
      }
    }
  }
}
class LoginRepository {
  LoginProvider _loginProvider;

  LoginRepository({LoginProvider loginProvider}) {
    _loginProvider = loginProvider ?? LoginProvider();
  }

  Future<String> authenticate({String email, String password}) async {
    if (email == null || password == null) {
      return "Nie podanu loginu lub hasła";
    }

    var loginData =
        await _loginProvider.login(email: email, password: password);
    var token = AuthToken.fromJson(loginData);
    return token.accessToken;
  }

  Future<bool> hasToken() async {
    String token = await LocalStorage.get(Constant.ACCESS_TOKEN);
    if (token != null) {
      return true;
    }
    return false;
  }

  Future<void> persistToken(String token) async {
    if (token != null) {
      await LocalStorage.save(Constant.ACCESS_TOKEN, "${Constant.TOKEN_TYPE_BEARER} $token");
    }
  }

  Future<void> deleteToken() async {
    await LocalStorage.remove(Constant.ACCESS_TOKEN);
  }
}
class LocalStorage {
  static save(String key, String value) async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    prefs.setString(key, value);
  }

  static Future<String> get(String key) async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    return prefs.get(key);
  }

  static remove(String key) async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    prefs.remove(key);
  }

  static removeAll() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    var keys = prefs.getKeys();
    keys.map((key) {
      remove(key);
    });
  }
}