Flutter:如何删除等待以利用 Firebase 离线持久性?
Posted
技术标签:
【中文标题】Flutter:如何删除等待以利用 Firebase 离线持久性?【英文标题】:Flutter: How to remove awaits to take advantage of Firebase Offline Persistence? 【发布时间】:2020-11-22 02:39:19 【问题描述】:我正在使用一个下拉列表(DropDown),它的元素是从 Firebase 获取的。该表单可以正常工作,但是当 Internet 连接丢失时,Firebase Offline Persistence 属性不起作用并且 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;
);
【问题讨论】:
您提供的链接谈论事务,当您未连接到服务器时,该链接将不起作用。您的代码不使用事务,因此据我所见,不受链接中所说内容的影响。当你运行它时,你的代码有什么问题? 谢谢弗兰克!!谢谢弗兰克。连接离线时,我无法使下拉菜单工作。除了这个链接,Medium link 还提到应该避免事务和等待。 这些链接中没有足够的上下文来理解它们在此处的应用方式。离线时,代码中的哪一行不起作用? 这一行... _alimentoList = await alimentoBloc.cargarAlimento(idEmpresa); 它有什么作用?你期望它做什么?如果您print
代码中的某些内容显示了您没有预料到的内容,通常最容易提供帮助。
【参考方案1】:
在离线使用 Firebase 时,您仅在更改服务器的操作(例如,创建或更新记录)上省略 await
。所以你不会等待服务器说“是的,我写了它”,你假设它已经写好了。
但是,在您的情况下,您不是在写入数据,而是在读取数据。您必须在示例中保留await
。您加载数据的方式有orderByChild
和startAt
,也许它们会阻止离线加载。通常,如果它已经在缓存中,你会得到它:https://firebase.google.com/docs/firestore/manage-data/enable-offline#get_offline_data
您提到了BAD STATE error
,也许如果您提供,我们也许可以更好地查明问题。
【讨论】:
以上是关于Flutter:如何删除等待以利用 Firebase 离线持久性?的主要内容,如果未能解决你的问题,请参考以下文章
Flutter:Google Maps 如何从 Firestore 设置图标
如何将 Flutter Bloc 与 Firebase 电话身份验证一起使用