如何在flutter中将streambuilder的自动setstate与手动setstate分开?

时间:2020-10-24 11:07:04

标签: flutter google-cloud-firestore stream-builder

我正在使用Streambuilder来侦听Firestore数据库中的更改并更新我的窗口小部件。但是我的问题是,当按下按钮时,我正在使用一些手动设置状态对代码进行视觉更改,这些设置状态还会触发streambuilder的设置状态并向用户显示额外的加载屏幕。如何获得单独的setstate?我应该使用其他东西代替streambuilder吗?

我的代码如下:

import 'package:flutter/material.dart';
import 'package:assets_audio_player/assets_audio_player.dart';
import 'numbers.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_core/firebase_core.dart';


Numbers myNumbers = Numbers();

void main(){
  runApp(
      GameScreen()
  );
}

class GameScreen extends StatefulWidget {
  static String id ='gamescreen';

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

class _GameScreenState extends State<GameScreen> {
  bool _initialized = false;
  bool _error = false;

  void initializeFlutterFire() async {
    try {
      // Wait for Firebase to initialize and set `_initialized` state to true
      await Firebase.initializeApp();
      setState(() {
        _initialized = true;
      });
    } catch(e) {
      // Set `_error` state to true if Firebase initialization fails
      setState(() {
        _error = true;
      });
    }
  }

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

  final _auth =FirebaseAuth.instance;
  User loggedInUser;
  final _firestore = FirebaseFirestore.instance;
  final String collectionPath = 'users';
  String docPath;
  DocumentReference userdoc;


  void getCurrentUser() async{
    try{
      final user = await _auth.currentUser;
      if(user !=null){
        loggedInUser =user;
        docPath = loggedInUser.uid;
      }
    }catch(e){
      print(e);
    }
  }


  Expanded attachNumber(imagenumber){
    return Expanded(
      child:FlatButton(
        onPressed: (){
          setState(() {
            if(!myNumbers.numberStatus[1]){
              myNumbers.buttonValues['numberimage1'] = imagenumber;
              myNumbers.numberStatus[1] =true;
            }else if(!myNumbers.numberStatus[2]){
              myNumbers.buttonValues['numberimage2'] = imagenumber;
              myNumbers.numberStatus[2] =true;
            }else if(!myNumbers.numberStatus[3]){
              myNumbers.buttonValues['numberimage3'] = imagenumber;
              myNumbers.numberStatus[3] =true;
            }else if(!myNumbers.numberStatus[4]){
              myNumbers.buttonValues['numberimage4'] = imagenumber;
              myNumbers.numberStatus[4] =true;
            }
          });
          final assetsAudioPlayer = AssetsAudioPlayer();
          assetsAudioPlayer.open(
            Audio("assets/audios/click.wav"),
          );
        },
        padding: EdgeInsets.all(0),
        child: Image.asset('images/$imagenumber'),
      ),
    );
  }

  FlatButton showDeleteNumbers(statusNumber,number){
    return FlatButton(
      onPressed: (){
        setState(() {
          myNumbers.numberStatus[statusNumber] =false;
          myNumbers.buttonValues[number] = 'nonumber.png';
        });
      },
      child: Image.asset('images/'+myNumbers.buttonValues['$number']),
    );
  }




  @override
  Widget build(BuildContext context) {
    userdoc = _firestore.collection(collectionPath).doc(docPath);
    if(_error) {
      return Text('error-game', textDirection: TextDirection.ltr);
    }

    // Show a loader until FlutterFire is initialized
    if (!_initialized) {
      return Text('Loading', textDirection: TextDirection.ltr);
    }
    return StreamBuilder<DocumentSnapshot>(
      stream: userdoc.snapshots(),
      builder: (BuildContext context, AsyncSnapshot<DocumentSnapshot> snapshot) {
        if (snapshot.hasError) {
          return Text('Something went wrong');
        }

        if (snapshot.connectionState == ConnectionState.waiting) {
          return Text("Loading");
        }
        if(snapshot.hasData){
          Map<String, dynamic> userDocument  = snapshot.data.data();
          print(collectionPath);
          print(docPath);
          print(snapshot.data);
          print(userDocument);
          return MaterialApp(
            home:Scaffold(
              appBar: AppBar(
                backgroundColor: Colors.amberAccent,
                title: Text('Sayı Avı Oyun Ekranı'),
              ),
              body:Column(
                children: <Widget>[
                  Expanded(
                    flex: 80,
                    child: Row(
                      children: <Widget>[
                        Expanded(
                          flex: 50,
                          child: Column(
                            children: myNumbers.getUserNumbers(),
                          ),
                        ),
                        Expanded(
                          flex: 50,
                          child: Column(
                            children: myNumbers.getOpponentNumbers(),
                          ),
                        ),
                      ],
                    ),
                  ),
                  Expanded(
                    flex:10,
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: <Widget>[
                        showDeleteNumbers(1,'numberimage1'),
                        showDeleteNumbers(2,'numberimage2'),
                        showDeleteNumbers(3,'numberimage3'),
                        showDeleteNumbers(4,'numberimage4'),
                      ],
                    ),
                  ),
                  Expanded(
                    flex: 10,
                    child: Row(
                      children: <Widget>[
                        attachNumber('one.png'),
                        attachNumber('two.png'),
                        attachNumber('three.png'),
                        attachNumber('four.png'),
                        attachNumber('five.png'),
                        attachNumber('six.png'),
                        attachNumber('seven.png'),
                        attachNumber('eight.png'),
                        attachNumber('nine.png'),
                        attachNumber('zero.png'),
                      ],
                    ),
                  ),
                ],
              ),
            ),
          );
        }
      },
    );
  }
}

1 个答案:

答案 0 :(得分:1)

尝试在initState中的变量中捕获流userdoc.snapshots(),而不是在每次构建中都调用快照方法。 这样,您可以确保streambuilder在每次构建时都获得相同的流,并在重新构建时可以保持其状态