Firebase 使用firestore调整提供程序,避免在更改页面时重复读取数据库

Firebase 使用firestore调整提供程序,避免在更改页面时重复读取数据库,firebase,flutter,flutter-provider,Firebase,Flutter,Flutter Provider,我正在从事一个关于颤振和Firebase(使用颤振火)的项目。 我正在寻找一个可以与Firebase一起使用的状态管理解决方案。 所以我了解了颤振提供者,并决定尝试一下 这是我目前的情况: 从my_scaffold.dart中,我获得底部导航索引并切换页面(左屏幕.dart、右屏幕.dart、仪表板屏幕.dart) 在db.dart内部,我保留了所有函数(包含Firestore查询),这些函数将为我提供所需的流 对于我的每个页面,我都有一些StreamProviders,它们向页面的子级提供数

我正在从事一个关于颤振和Firebase(使用颤振火)的项目。 我正在寻找一个可以与Firebase一起使用的状态管理解决方案。 所以我了解了颤振提供者,并决定尝试一下

这是我目前的情况:

从my_scaffold.dart中,我获得底部导航索引并切换页面(左屏幕.dart、右屏幕.dart、仪表板屏幕.dart)

在db.dart内部,我保留了所有函数(包含Firestore查询),这些函数将为我提供所需的流

对于我的每个页面,我都有一些StreamProviders,它们向页面的子级提供数据

问题是:

每次我切换页面时,StreamProviders都会被解构,并最终在我回到该页面时重新构建

这样,每次用户切换页面时,我都会从Firestore读取数据,即使上次打开该页面时我需要的数据已经在设备上了

我怎样才能避免这样的阅读浪费?我考虑在第一次读取时将值存储在某个位置,如果没有更改,则避免读取,但要了解Firestore中的更改,我需要读取

以下是我的一些代码:

dashboard_screen.dart:

class DashboardScreen extends StatefulWidget {
  @override
  __DashboardScreenState  createState() => __DashboardScreenState ();
}

class _DashboardScreenState extends State<DashboardScreen> {
  @override
  Widget build(BuildContext context) {
    var user = Provider.of<User>(context);
    return MultiProvider(
      providers: [
        StreamProvider(
            create: (BuildContext context) =>
                DatabaseService().streamUtente(user.uid)),
        StreamProvider(
            create: (BuildContext context) =>
                DatabaseService().streamDatiPolizze(user.uid)),
        StreamProvider(
            create: (BuildContext context) =>
                DatabaseService().streamDatiClienti(user.uid)),
        StreamProvider(
            create: (BuildContext context) =>
                DatabaseService().streamPolizzeInScadenza(user.uid)),
      ],
      child: SafeArea(
        child: SingleChildScrollView(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: [
              PageTitle(),
              ValorePortafoglio(),
              IncassoGuadagno(),
              PolizzeInScadenza()
            ],
          ),
        ),
      ),
    );
  }
}
class DashboardScreen扩展了StatefulWidget{
@凌驾
__仪表板屏幕状态createState()=>u仪表板屏幕状态();
}
类_仪表板屏幕状态扩展状态{
@凌驾
小部件构建(构建上下文){
var user=Provider.of(上下文);
回程多供应商(
供应商:[
流提供者(
创建:(BuildContext上下文)=>
DatabaseService().streamute(user.uid)),
流提供者(
创建:(BuildContext上下文)=>
DatabaseService().StreamDatiPolize(user.uid)),
流提供者(
创建:(BuildContext上下文)=>
DatabaseService().streamDatiClienti(user.uid)),
流提供者(
创建:(BuildContext上下文)=>
DatabaseService().streamPolizzeInScadenza(user.uid)),
],
儿童:安全区(
子:SingleChildScrollView(
子:列(
crossAxisAlignment:crossAxisAlignment.stretch,
儿童:[
PageTitle(),
从价税(),
IncassoGuadagno(),
PolizzeInScadenza()
],
),
),
),
);
}
}
valore_Portafglio.dart(其中一个孩子):

class valoreportafglio扩展了无状态小部件{
从价差({
关键点,
}):super(key:key);
@凌驾
小部件构建(构建上下文){
Datipolize Datipolize=
提供程序(上下文)??Datipolize.DefaultDatipolize();
DatiClienti DatiClienti=
提供程序(上下文)??DatiClienti.defaultDatiClienti();
Size Size=MediaQuery.of(context).Size;
返回填充(
padding:const EdgeInsets.symmetric(水平:kDefaultPadding),
子:Neormorphic容器(
子:列(
crossAxisAlignment:crossAxisAlignment.stretch,
儿童:[
RichText(
text:TextSpan(子项:[
TextSpan(
文本:“Valore del Portafglio\n”,
样式:Theme.of(context).textTheme.headline5.copyWith(
颜色:kTextColor。不透明度(0.5),
fontWeight:fontWeight.正常),
),
TextSpan(
正文:“${datipolize.valore}€”,
风格:主题(上下文)
.文本主题
.标题3
.copyWith(颜色:kTextColor,fontwweight:fontwweight.bold),
),
]),
),
填充物(
填充:仅限常量边集(顶部:kDefaultPadding*0.5),
孩子:排(
mainAxisAlignment:mainAxisAlignment.spaceAround,
儿童:[
正文(
“${datiClienti.numero.toStringAsFixed(0)}Clienti”,
样式:Theme.of(context).textTheme.headline6.copyWith(
颜色:kTextColor,fontWeight:fontWeight.normal),
),
填充物(
填充:const EdgeInsets.symmetric(
水平方向:kDefaultPadding*0.8),
子:容器(
高度:size.height*0.03,
宽度:2,
颜色:kDarkColor。不透明度(0.3),
),
),
正文(
“${datiPolizze.numero.toStringAsFixed(0)}Polizze”,
样式:Theme.of(context).textTheme.headline6.copyWith(
颜色:kTextColor,fontWeight:fontWeight.normal),
),
],
),
)
],
),
),
);
}
}
省道

class DatabaseService {
  final FirebaseFirestore _db = FirebaseFirestore.instance;

  /// Get a stream of a single document
  Stream<Utente> streamUtente(String id) {
    return _db
        .collection('users')
        .doc(id)
        .snapshots()
        .map((snap) => Utente.fromFirestore(snap));
  }

  Stream<List<Polizza>> streamPolizze(String id) {
    var ref = _db.collection('polizze').doc(id).collection('elenco');

    return ref.snapshots().map(
        (list) => list.docs.map((doc) => Polizza.fromFirestore(doc)).toList());
  }

  Stream<List<Polizza>> streamPolizzeInScadenza(String id) {
    var start = "${DateFormat('yyyy-MM').format(DateTime.now())}-01";
    var end = "${DateFormat('yyyy-MM').format(DateTime.now())}-31";
    var ref = _db
        .collection('polizze')
        .doc(id)
        .collection('elenco')
        .where('scadenza', isGreaterThanOrEqualTo: start)
        .where('scadenza', isLessThanOrEqualTo: end);

    return ref.snapshots().map(
        (list) => list.docs.map((doc) => Polizza.fromFirestore(doc)).toList());
  }

  Stream<DatiPolizze> streamDatiPolizze(String id) {
    return _db
        .collection('polizze')
        .doc(id)
        .snapshots()
        .map((snap) => DatiPolizze.fromFirestore(snap));
  }

  Stream<DatiClienti> streamDatiClienti(String id) {
    return _db
        .collection('clienti')
        .doc(id)
        .snapshots()
        .map((snap) => DatiClienti.fromFirestore(snap));
  }

  static login(String email, String password) async {
    try {
      UserCredential userCredential = await FirebaseAuth.instance
          .signInWithEmailAndPassword(email: email, password: password);
    } on FirebaseAuthException catch (e) {
      if (e.code == 'user-not-found') {
        print('No user found for that email.');
      } else if (e.code == 'wrong-password') {
        print('Wrong password provided for that user.');
      }
    }
  }

  static logout() async {
    try {
      await FirebaseAuth.instance.signOut();
    } on FirebaseAuthException catch (e) {
      print('Error');
    }
  }
}
类数据库服务{
最终FirebaseFirestore _db=FirebaseFirestore.instance;
///获取单个文档的流
streamUtente流(字符串id){
返回_db
.collection('用户')
.doc(id)
.快照()
.map((snap)=>int.fromFirestore(snap));
}
streamPolizze(字符串id){
var ref=_db.collection('polizze').doc(id).collection('elenco');
返回参考快照().map(
(list)=>list.docs.map((doc)=>Polizza.fromFirestore(doc)).toList();
}
Stream streamPolizzeInScadenza(字符串id){
var start=“${DateFormat('yyyy-MM').format(DateTime.now())}-01”;
var end=“${DateFormat('yyyy-MM').format(DateTime.now())}-31”;
var ref=_db
.collection(“polizze”)
.doc(id)
.collection('elenco')
.where('scadenza',大于或等于:开始)
.wh
class DatabaseService {
  final FirebaseFirestore _db = FirebaseFirestore.instance;

  /// Get a stream of a single document
  Stream<Utente> streamUtente(String id) {
    return _db
        .collection('users')
        .doc(id)
        .snapshots()
        .map((snap) => Utente.fromFirestore(snap));
  }

  Stream<List<Polizza>> streamPolizze(String id) {
    var ref = _db.collection('polizze').doc(id).collection('elenco');

    return ref.snapshots().map(
        (list) => list.docs.map((doc) => Polizza.fromFirestore(doc)).toList());
  }

  Stream<List<Polizza>> streamPolizzeInScadenza(String id) {
    var start = "${DateFormat('yyyy-MM').format(DateTime.now())}-01";
    var end = "${DateFormat('yyyy-MM').format(DateTime.now())}-31";
    var ref = _db
        .collection('polizze')
        .doc(id)
        .collection('elenco')
        .where('scadenza', isGreaterThanOrEqualTo: start)
        .where('scadenza', isLessThanOrEqualTo: end);

    return ref.snapshots().map(
        (list) => list.docs.map((doc) => Polizza.fromFirestore(doc)).toList());
  }

  Stream<DatiPolizze> streamDatiPolizze(String id) {
    return _db
        .collection('polizze')
        .doc(id)
        .snapshots()
        .map((snap) => DatiPolizze.fromFirestore(snap));
  }

  Stream<DatiClienti> streamDatiClienti(String id) {
    return _db
        .collection('clienti')
        .doc(id)
        .snapshots()
        .map((snap) => DatiClienti.fromFirestore(snap));
  }

  static login(String email, String password) async {
    try {
      UserCredential userCredential = await FirebaseAuth.instance
          .signInWithEmailAndPassword(email: email, password: password);
    } on FirebaseAuthException catch (e) {
      if (e.code == 'user-not-found') {
        print('No user found for that email.');
      } else if (e.code == 'wrong-password') {
        print('Wrong password provided for that user.');
      }
    }
  }

  static logout() async {
    try {
      await FirebaseAuth.instance.signOut();
    } on FirebaseAuthException catch (e) {
      print('Error');
    }
  }
}