firebase - Flutter:如何删除等待以利用 Firebase 离线持久性?

标签 firebase flutter firebase-realtime-database async-await

我正在使用下拉列表 (DropDown),其元素是从 Firebase 获取的。该表单工作正常,但是当互联网连接丢失时,Firebase 离线持久性属性不起作用并且 CircularProgressIndicator 保持事件状态。阅读一些回复,例如 Using Offline Persistence in Firestore in a Flutter App ,表示不应处理等待 ,但是我不清楚如何实现它:

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
  }
}
我的 BLOC 的功能代码是:
  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;
  }); 

最佳答案

离线使用 Firebase 时,请省略 await仅在更改服务器的事情上(例如,创建或更新记录)。所以你不会等待服务器说“是我写的”,你假设它已经写好了。
但是,就您而言,您不是在写入数据,而是在读取数据。您必须保留 await在你的例子中。你加载数据的方式有 orderByChildstartAt ,也许那些正在阻止离线加载。通常,如果它已经在缓存中,你就会得到它:https://firebase.google.com/docs/firestore/manage-data/enable-offline#get_offline_data
你提到了 BAD STATE error ,也许如果您提供该信息,我们可能能够更好地查明问题。

关于firebase - Flutter:如何删除等待以利用 Firebase 离线持久性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63205559/

相关文章:

java - 用户注销并再次登录后,Firebase facebook 登录错误将您记录到应用程序中

Swift Firebase 查询 child 的 child

flutter - 如何在 flutter Dart 中从两个字符串生成一个字符串/哈希

ios - Firebase - 对象数组未返回正常计数值

java - Firebase 实时数据库中的节点是什么?

firebase - 如何限制 Firebase Firestore 集合中的文档

firebase - 在 Cloud Functions for Firebase 中访问数据库数据

dart - 错误 : The argument type '(File) → Future<dynamic>' can't be assigned to the parameter type '(dynamic) → FutureOr<dynamic>'

android - 用户向上滚动时无法单击 SliverPersistentHeader 上的操作按钮

java - 将泛型与 Firebase snapshot.getValue() 结合使用的最佳实践