Flutter: как удалить ожидания, чтобы воспользоваться преимуществами Firebase Offline Persistence? - PullRequest
0 голосов
/ 01 августа 2020

Я использую раскрывающийся список (DropDown), элементы которого получены из Firebase. Форма работает правильно, однако, когда соединение inte rnet потеряно, свойство Firebase Offline Persistence не работает и CircularProgressIndicator остается активным. Читая некоторые ответы, такие как Использование автономного сохранения в Firestore в приложении Flutter , указывается, что awaits не следует обрабатывать , однако мне не ясно, как этого добиться:

class EstanqueAlimentarPage extends StatefulWidget {

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

class _EstanqueAlimentarPageState extends State<EstanqueAlimentarPage> {
  final formKey = GlobalKey<FormState>();
  AlimentoBloc alimentoBloc = new AlimentoBloc();
  AlimentoModel _alimento = new AlimentoModel();
  AlimentarModel alimentar = new AlimentarModel();
  List<AlimentoModel> _alimentoList;
  bool _alimentoDisponible = true;

@override
  void dispose() {
    alimentoBloc.dispose();
    super.dispose();
  }

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


Future<void> _obtenerListaAlimentoUnaVez() async {
  
  _alimentoList = await alimentoBloc.cargarAlimento(idEmpresa); // Await that I want to eliminate

  if (_alimentoList.length > 0) { // Here appears a BAD STATE error when the internet connection goes from off to on
    _alimento = _alimentoList[0];
    _alimentoDisponible = true;
  } else {
    _alimentoDisponible = false;
  }
  _cargando = false;
  setState(() {});
}

  @override
  Widget build(BuildContext context) {
    
    return Form(
      key: formKey, 
      child: Column(
        children: <Widget> [
          _crearTipoAlimento(_alimentoList),
          SizedBox(height: 8.0),
          _crearComentarios(),
        ]
      )
    ),
    _crearBoton('Guardar'),

  }

  Widget _crearTipoAlimento(List<AlimentoModel> lista) {

    return Container(
      decoration: _cajaBlanca,
      child: 
      !_cargando // If it isn't loading, Dropdown must be displayed
      ? DropdownButtonFormField<AlimentoModel>(
        decoration: InputDecoration(
          labelText: 'Nombre del Alimento',
          contentPadding: EdgeInsets.only(top:5.0),
          prefixIcon: Icon(FontAwesomeIcons.boxOpen, color: Theme.of(context).primaryColor,),
          border: InputBorder.none,
        ),
        value: _alimento,
        items: lista.map((AlimentoModel value) {
          return DropdownMenuItem<AlimentoModel>(
            child: Text(value.nombre),
            value: value,
          );
        }).toList(),
        onChanged: (_alimentoDisponible) ? (AlimentoModel _alimentoSeleccionado) {
          print(_alimentoSeleccionado.nombre);
          _alimento = _alimentoSeleccionado;
          setState(() {});
        } : null,
        disabledHint: Text('No hay Alimento en Bodega'),
        onSaved: (value) {
          alimentar.idAlimento = _alimento.idAlimento;
          alimentar.nombreAlimento = _alimento.nombreRef; 
        }
      )
      : Center (child: CircularProgressIndicator(strokeWidth: 1.0,))

    );
  }

  Widget _crearComentarios() {
    return TextFormField(
      // -- DESIGN OTHER FIELDS -- //
      onSaved: (value) {
        alimentar.comentarios = value;
      }
    ),
    );
  }

  Widget _crearBoton(String texto) {
    return RaisedButton(
        // -- DESIGN -- //
        onPressed: (_guardando) ? null : _submit,
      ),
    );
  }

  void _submit() {

    // CODE TO WRITE FORM IN FIREBASE
  }
}

Код функции из моего BLO C:

  Future<List<AlimentoModel>> cargarAlimento(String idEmpresa, [String filtro]) async {
    final alimento = await _alimentoProvider.cargarAlimento(idEmpresa, filtro); //It's one await more
    _alimentoController.sink.add(alimento);
    return alimento;
  }

А запрос от PROVIDER:

Future<List<AlimentoModel>> cargarAlimento(String idEmpresa, [String filtro]) async {

    Query resp;
    final List<AlimentoModel> alimento = new List(); 
    resp = db.child('empresas').child(idEmpresa).child('bodega/1').child('alimento')
            .orderByChild('cantidad').startAt(0.000001);
 
  return resp.once().then((snapshot) {

      if (snapshot.value == null) return [];
      if (snapshot.value['error'] != null) return []; 

      snapshot.value.forEach((id, alim){
        final temp = AlimentoModel.fromJson(Map<String,dynamic>.from(alim));
        temp.idAlimento = id;

        alimento.add(temp);
      });
      return alimento;
  }); 

1 Ответ

1 голос
/ 01 августа 2020

При использовании Firebase в автономном режиме вы опускаете await только для вещей, которые изменяют сервер (например, создание или обновление записи). Таким образом, вы не будете ждать, пока сервер скажет «да, я написал», вы предполагаете, что он записан.

Однако в вашем случае вы не пишете данные, вы читаете данные. В вашем примере вам нужно будет оставить await. В способе загрузки данных указаны orderByChild и startAt, возможно, они препятствуют загрузке в автономном режиме. Обычно вы получаете его, если он уже находится в кеше: https://firebase.google.com/docs/firestore/manage-data/enable-offline#get_offline_data

Вы упоминаете BAD STATE error, возможно, если вы предоставите это, мы сможем немного определить проблему лучше.

...