Что я делаю не так с этим BloC и SharedPreferences? - PullRequest
0 голосов
/ 11 июня 2019

Возобновление проблемы: после перезапуска приложения настройки становятся нулевыми.

Я создаю экран входа в систему с помощью одной кнопки «Настройки» на панели приложений, и каждый раз, когда я перезагружаю приложение, сохраненные настройки отображаются как «удаленные». Я использую библиотеку Bloc.

Я также хотел бы получить несколько предложений по улучшению кода:).

Состояние BloC

import 'package:equatable/equatable.dart';
import 'package:meta/meta.dart';
import 'package:visiogate/vg_models/webApiConfigs/webapi_model.dart';

@immutable
abstract class WebApiConfigsState extends Equatable {
  WebApiConfigsState([List props = const []]) : super(props);
}

//Load(ing)
class WebApiConfigsLoading extends WebApiConfigsState {
  final WebApiConfigs webApiConfigs;

  WebApiConfigsLoading({this.webApiConfigs}) : super([webApiConfigs]);

  @override
  String toString() => 'WebApiConfigsLoading';
}

//Load
class WebApiConfigsLoaded extends WebApiConfigsState {
  final WebApiConfigs webApiConfigs;

  WebApiConfigsLoaded({this.webApiConfigs}) : super([webApiConfigs]);

  @override
  String toString() => 'WebApiConfigsLoaded';
}

//Save
class WebApiConfigsSaving extends WebApiConfigsState {
  final WebApiConfigs webApiConfigs;

  WebApiConfigsSaving({this.webApiConfigs}) : super([webApiConfigs]);

  @override
  String toString() => 'WebApiConfigsSaving';
}

//Save(d)
class WebApiConfigsSaved extends WebApiConfigsState {
  final WebApiConfigs webApiConfigs;

  WebApiConfigsSaved({this.webApiConfigs}) : super([webApiConfigs]);

  @override
  String toString() => 'WebApiConfigsSaving';
}

//Erro
class WebApiConfigsError extends WebApiConfigsState {
  final String error;

  WebApiConfigsError({@required this.error}) : super([error]);

  @override
  String toString() => 'WebApiConfigsError { error: $error }';
}

BloC Event

import 'package:equatable/equatable.dart';

import 'package:visiogate/vg_models/webApiConfigs/webapi_model.dart';

abstract class WebApiConfigsEvent extends Equatable {}

//Load
class LoadWebApiConfigsEvent extends WebApiConfigsEvent {
  WebApiConfigs webApiConfigs;

  LoadWebApiConfigsEvent(this.webApiConfigs);

  @override
  String toString() => 'LoadWebApiConfigsEvent';
}

//Save
class SaveWebApiConfigsEvent extends WebApiConfigsEvent {
  final WebApiConfigs webApiConfigs;

  SaveWebApiConfigsEvent(this.webApiConfigs);

  @override
  String toString() => 'SaveWebApiConfigsEvent { URL: ${webApiConfigs.url} }';
}

BloC Bloc

import 'package:bloc/bloc.dart';

import 'package:visiogate/vg_blocs/webApiConfigs/webApiConfigs.dart';
import 'package:visiogate/vg_blocs/simple_bloc_delegate.dart';
import 'package:visiogate/vg_models/persistent_data/persistent_data.dart';
import 'package:visiogate/vg_models/webApiConfigs/webapi_model.dart';

void main() {
  BlocSupervisor.delegate = SimpleBlocDelegate();
}

class WebApiConfigsBloc extends Bloc<WebApiConfigsEvent, WebApiConfigsState> {
  PersistentData _persistentData = new PersistentData();
  WebApiConfigs _wac = new WebApiConfigs("", "", "", "", "", "");

  @override
  WebApiConfigsState get initialState =>
      WebApiConfigsLoading(webApiConfigs: _wac);

  @override
  Stream<WebApiConfigsState> mapEventToState(
    WebApiConfigsEvent event,
  ) async* {
    //Load
    if (event is LoadWebApiConfigsEvent) {
      try {
        final WebApiConfigs _wac = await _persistentData.getApiConfigs();
        yield WebApiConfigsLoaded(webApiConfigs: _wac);
      } catch (error) {
        yield WebApiConfigsError(error: error.toString());
      }
    }
    //Save
    if (event is SaveWebApiConfigsEvent) {
      try {
        yield WebApiConfigsSaving(webApiConfigs: event.webApiConfigs);
        yield WebApiConfigsSaved(webApiConfigs: event.webApiConfigs);
      } catch (error) {
        yield WebApiConfigsError(error: error.toString());
      }
    }
  }
}

Форма

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

import 'package:visiogate/vg_blocs/webApiConfigs/webApiConfigs.dart';
import 'package:visiogate/vg_models/webApiConfigs/webapi_model.dart';

class ConfigsForm extends StatefulWidget {
  final WebApiConfigsBloc webApiConfigsBloc;

  const ConfigsForm({Key key, @required this.webApiConfigsBloc})
      : super(key: key);

  @override
  _ConfigsFormState createState() => _ConfigsFormState();
}

class _ConfigsFormState extends State<ConfigsForm> {
  final _urlController = TextEditingController();
  final _companyController = TextEditingController();

  WebApiConfigsBloc get _webApiConfigsBloc => widget.webApiConfigsBloc;

  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return BlocBuilder<WebApiConfigsEvent, WebApiConfigsState>(
      bloc: _webApiConfigsBloc,
      builder: (
        BuildContext context,
        WebApiConfigsState state,
      ) {
        if (state is WebApiConfigsError) {
          _onWidgetDidBuild(() {
            Scaffold.of(context).showSnackBar(
              SnackBar(
                content: Text('${state.error}'),
                backgroundColor: Colors.red,
              ),
            );
          });
        } else if (state is WebApiConfigsLoading) {
          _webApiConfigsBloc
              .dispatch(LoadWebApiConfigsEvent(state.webApiConfigs));
        } else if (state is WebApiConfigsLoaded) {
          _urlController.text = state.webApiConfigs.url;
          _companyController.text = state.webApiConfigs.company;
          //TODO: showSnackBar
        } else if (state is WebApiConfigsSaved) {
          _urlController.text = state.webApiConfigs.url;
          _companyController.text = state.webApiConfigs.company;
          //TODO: showSnackBar
        }

        return Column(
          children: <Widget>[
            Form(
              child: Column(
                children: [
                  TextFormField(
                    decoration: InputDecoration(labelText: 'url'),
                    controller: _urlController,
                  ),
                  TextFormField(
                    decoration: InputDecoration(labelText: 'company'),
                    controller: _companyController,
                  ),
                  RaisedButton(
                    onPressed: state is! WebApiConfigsLoading
                        ? _onSaveConfigsButtonPressed
                        : null,
                    child: Text('save'),
                  ),
                  Container(
                    child: state is WebApiConfigsLoading
                        ? CircularProgressIndicator()
                        : null,
                  ),
                ],
              ),
            ),
          ],
        );
      },
    );
  }

  void _onWidgetDidBuild(Function callback) {
    WidgetsBinding.instance.addPostFrameCallback((_) {
      callback();
    });
  }

  _onSaveConfigsButtonPressed() {
    //TODO: fazer restantes controlos
    WebApiConfigs _wac = new WebApiConfigs(
        _urlController.text,
        _companyController.text,
        "default",
        "bearer",
        "professional",
        "password");

    _webApiConfigsBloc.dispatch(SaveWebApiConfigsEvent(
      _wac,
    ));
  }
}

SharedPreferences

import 'package:shared_preferences/shared_preferences.dart';

import 'package:visiogate/vg_models/webApiConfigs/webapi_model.dart';
import 'package:visiogate/vg_models/token/token.dart';

class PersistentData {
  String _apiUrl = "api_url";
  String _apiCompany = "api_company";
  String _apiInstance = "api_instance";
  String _apiAuthorization = "api_authorization";
  String _apiLine = "api_line";
  String _apiGrantType = "api_grant_type";

  Future<void> setApiConfigs(WebApiConfigs webapi) async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    prefs.setString(_apiUrl, webapi.url);
    prefs.setString(_apiCompany, webapi.company);
    prefs.setString(_apiInstance, webapi.instance);
    prefs.setString(_apiAuthorization, webapi.authorization);
    prefs.setString(_apiLine, webapi.line);
    prefs.setString(_apiGrantType, webapi.grantType);
    return;
  }

  Future<WebApiConfigs> getApiConfigs() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    String _ur = prefs.getString(_apiUrl) ?? "";
    String _co = prefs.getString(_apiCompany) ?? "";
    String _ins = prefs.getString(_apiInstance) ?? "D";
    String _au = prefs.getString(_apiAuthorization) ?? "bearer";
    String _ln = prefs.getString(_apiLine) ?? "pro";
    String _gt = prefs.getString(_apiGrantType) ?? "pwd";

    WebApiConfigs webapi = new WebApiConfigs(_ur, _co, _ins, _au, _ln, _gt);
    return webapi;
  }
}

Если я не перезагружаю приложение, все «сохраненные» конфиги есть! Что я делаю неправильно? Вероятно, это просто простая линия, но ... она сводит меня с ума!

TY in andvance.

1 Ответ

0 голосов
/ 11 июня 2019

После кофе и свежего воздуха на моем лице ...

Проблема была в Форме и в Блоке. Вот код, чтобы ни одна другая душа не сошла с ума, а также мой вклад в сообщество:

Блок BloC

import 'package:bloc/bloc.dart';

import 'package:visiogate/vg_blocs/webApiConfigs/webApiConfigs.dart';
import 'package:visiogate/vg_blocs/simple_bloc_delegate.dart';
import 'package:visiogate/vg_models/persistent_data/persistent_data.dart';
import 'package:visiogate/vg_models/webApiConfigs/webapi_model.dart';

void main() {
  BlocSupervisor.delegate = SimpleBlocDelegate();
}

class WebApiConfigsBloc extends Bloc<WebApiConfigsEvent, WebApiConfigsState> {
  PersistentData _persistentData = new PersistentData();
  WebApiConfigs _wac = new WebApiConfigs("", "", "", "", "", "");

  @override
  WebApiConfigsState get initialState =>
      WebApiConfigsLoading(webApiConfigs: _wac);

  @override
  Stream<WebApiConfigsState> mapEventToState(
    WebApiConfigsEvent event,
  ) async* {
    //Load
    if (event is LoadWebApiConfigsEvent) {
      try {
        event.webApiConfigs = await _persistentData.getApiConfigs();
        yield WebApiConfigsLoaded(webApiConfigs: event.webApiConfigs);
      } catch (error) {
        yield WebApiConfigsError(error: error.toString());
      }
    }
    //Save
    if (event is SaveWebApiConfigsEvent) {
      try {
        _persistentData.setApiConfigs(event.webApiConfigs);
        yield WebApiConfigsSaving(webApiConfigs: event.webApiConfigs);
        yield WebApiConfigsLoaded(webApiConfigs: event.webApiConfigs);
      } catch (error) {
        yield WebApiConfigsError(error: error.toString());
      }
    }
  }
}

Форма

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

import 'package:visiogate/vg_blocs/webApiConfigs/webApiConfigs.dart';
import 'package:visiogate/vg_models/webApiConfigs/webapi_model.dart';

class ConfigsForm extends StatefulWidget {
  final WebApiConfigsBloc webApiConfigsBloc;

  const ConfigsForm({Key key, @required this.webApiConfigsBloc})
      : super(key: key);

  @override
  _ConfigsFormState createState() => _ConfigsFormState();
}

class _ConfigsFormState extends State<ConfigsForm> {
  final _urlController = TextEditingController();
  final _companyController = TextEditingController();

  WebApiConfigsBloc get _webApiConfigsBloc => widget.webApiConfigsBloc;

  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return BlocBuilder<WebApiConfigsEvent, WebApiConfigsState>(
      bloc: _webApiConfigsBloc,
      builder: (
        BuildContext context,
        WebApiConfigsState state,
      ) {
        if (state is WebApiConfigsError) {
          _onWidgetDidBuild(() {
            Scaffold.of(context).showSnackBar(
              SnackBar(
                content: Text('${state.error}'),
                backgroundColor: Colors.red,
              ),
            );
          });
        } else if (state is WebApiConfigsLoading) {
          _webApiConfigsBloc
              .dispatch(LoadWebApiConfigsEvent(state.webApiConfigs));
        } else if (state is WebApiConfigsSaving) {
          _urlController.text = state.webApiConfigs.url;
          _companyController.text = state.webApiConfigs.company;
          //TODO: showSnackBar
        } else if (state is WebApiConfigsLoaded) {
          _urlController.text = state.webApiConfigs.url;
          _companyController.text = state.webApiConfigs.company;
          //TODO: showSnackBar
        }

        return Column(
          children: <Widget>[
            Form(
              child: Column(
                children: [
                  TextFormField(
                    decoration: InputDecoration(labelText: 'url'),
                    controller: _urlController,
                  ),
                  TextFormField(
                    decoration: InputDecoration(labelText: 'company'),
                    controller: _companyController,
                  ),
                  RaisedButton(
                    onPressed: (state is! WebApiConfigsLoading)
                        ? _onSaveConfigsButtonPressed
                        : null,
                    child: Text('save'),
                  ),
                  Container(
                    child: (state is WebApiConfigsLoading)
                        ? CircularProgressIndicator()
                        : null,
                  ),
                ],
              ),
            ),
          ],
        );
      },
    );
  }

  void _onWidgetDidBuild(Function callback) {
    WidgetsBinding.instance.addPostFrameCallback((_) {
      callback();
    });
  }

  _onSaveConfigsButtonPressed() {
    WebApiConfigs _wac = new WebApiConfigs(
        _urlController.text,
        _companyController.text,
        "d",
        "bearer",
        "pro",
        "pwd");

    _webApiConfigsBloc.dispatch(SaveWebApiConfigsEvent(
      _wac,
    ));
  }
}

Основная проблема заключалась в том, что я использовал переменную «_wac» вместо «event.webApiConfigs» в BloC. Также удалено состояние «WebApiConfigsSaved», поскольку оно имеет тот же окончательный вариант с «WebApiConfigsLoaded».

Приветствие.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...