База данных Flutter в реальном времени с помощью коммутатора - PullRequest
0 голосов
/ 10 июля 2020

Я пытаюсь реализовать переключатель, который считывает и записывает значение bool в моем хранилище с помощью следующего ключа Device / Device1 / LED_STATUS / DATA

Когда я запускаю getStatus, значение печатает null, а затем дает значение . Виджет получает сборку до того, как функция сможет выдать значение, и поэтому выдает исключение с нулевым утверждением и аварийно завершает работу. Я пробовал много методов, пытаясь настроить initState на setState, но бесполезно.

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:firebase_database/firebase_database.dart';



class SwitchPage extends StatefulWidget {
  static const String id = 'switch_screen';

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

class _SwitchPageState extends State<SwitchPage> {
  final DBref = FirebaseDatabase.instance.reference();


  bool isSwitched;

  void LedOn() async {
    await DBref.child("DHT11")
        .child("Device1")
        .child("LED_STATUS")
        .update({'DATA': 'TRUE'});
  }

  void LedOFF() async {
    await DBref.child("DHT11")
        .child("Device1")
        .child("LED_STATUS")
        .update({'DATA': 'FALSE'});
  }

  Future<bool> getStatus() async {
    bool isSwitched = (await FirebaseDatabase.instance
            .reference()
            .child("DHT11/Device1/LED_STATUS/DATA")
            .once())
        .value;
    print(isSwitched);
    return isSwitched;
  }

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
          appBar: AppBar(
            title: Text('Device Center'),
          ),
          backgroundColor: Colors.white,
          body: Column(
            children: <Widget>[
              FlatButton(
                  onPressed: () {
                    getStatus();
                    print(isSwitched);
                  },
                  child: Text('TEST')),
              Switch(
                value: isSwitched,
                onChanged: (value) {
                  if (isSwitched == 'TRUE') {
                    return LedOFF();
                  } else {
                    LedOn();
                  }
                },
              )

            ],
          )),
    );
  }
}

ОБНОВЛЕНО ПОСЛЕ ПРЕДЛОЖЕНИЙ

Я попробовал предложенные способы, которыми моя кнопка ТЕСТ работает нормально, они обновляются база данных firebase, но я не могу реализовать Switch! Пожалуйста, помогите!

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:firebase_database/firebase_database.dart';


class SwitchPage extends StatefulWidget {
  static const String id = 'switch_screen';

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

class _SwitchPageState extends State<SwitchPage> {
  final DBref = FirebaseDatabase.instance.reference();

  bool isSwitched;
  bool newVal;


  void LedOn() async {
    await DBref.child("DHT11")
        .child("Device1")
        .child("LED_STATUS")
        .update({'DATA': 'TRUE'});
  }

  void LedOFF() async {
    await DBref.child("DHT11")
        .child("Device1")
        .child("LED_STATUS")
        .update({'DATA': 'FALSE'});
  }

  void getStatus() async {
    String newValue = (await FirebaseDatabase.instance
            .reference()
            .child("DHT11/Device1/LED_STATUS/DATA")
            .once())
        .value;
    print(isSwitched);
    print(newValue);
    setState(() {
      if (newValue == 'TRUE') {
        isSwitched = true;
      } else {
        isSwitched = false;
      }
    });
  }


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

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
          appBar: AppBar(
            title: Text('Device Center'),
          ),
          backgroundColor: Colors.white,
          body: Column(
            children: <Widget>[
              FlatButton(
                  onPressed: () async {
                    await getStatus();
                  },
                  child: Text('TEST STATUS')),
              FlatButton(
                  onPressed: () {
                    LedOn();
                    print('ON');
                  },
                  child: Text('LED ON')),
              FlatButton(
                  onPressed: () {
                    LedOFF();
                    print('OFF');
                  },
                  child: Text('LED OFF')),
              Switch(
                value: isSwitched,
                onChanged: (value) {
                  setState(() {
                    isSwitched = value;
                    if (isSwitched == "TRUE") {
                      return LedOFF();
                    } else if (isSwitched == "FALSE") {
                      return LedOn();
                    }
                  });
                },
              ),
            ],
          )),
    );
  }
}

Ответы [ 2 ]

0 голосов
/ 10 июля 2020

Вы должны сделать что-то подобное в методе getStatus

void getStatus() async {
    String newValue = (await FirebaseDatabase.instance
            .reference()
            .child("DHT11/Device1/LED_STATUS/DATA")
            .once())
        .value;
    print(isSwitched);
    setState(() {
         if( newValue == 'TRUE' ) {
              isSwitched = true;
        }
        else {
             isSwitched = false;
        }
    });
  }

, тогда в FlatButton onPressed вы должны сделать что-то вроде этого

    onPressed: () async {
        await getStatus();
        print(isSwitched);
    },          

ОБНОВЛЕННЫЙ КОД на основании нового требования

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:firebase_database/firebase_database.dart';


class SwitchPage extends StatefulWidget {
  static const String id = 'switch_screen';

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

class _SwitchPageState extends State<SwitchPage> {
  final DBref = FirebaseDatabase.instance.reference();

  bool isSwitched;
  bool newVal;


  void LedOn() async {
    await DBref.child("DHT11")
        .child("Device1")
        .child("LED_STATUS")
        .update({'DATA': 'TRUE'});
  }

  void LedOFF() async {
    await DBref.child("DHT11")
        .child("Device1")
        .child("LED_STATUS")
        .update({'DATA': 'FALSE'});
  }

  void getStatus() async {
    String newValue = (await FirebaseDatabase.instance
            .reference()
            .child("DHT11/Device1/LED_STATUS/DATA")
            .once())
        .value;
    print(isSwitched);
    print(newValue);
    setState(() {
      if (newValue == 'TRUE') {
        isSwitched = true;
      } else {
        isSwitched = false;
      }
    });
  }
  
  void _handleSwitch(bool value) async {
    if( value ) {
        await LedOn();
    } else {
        await LedOFF();
    }
    setState(() {
        isSwitched = value;
    });
  }


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

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
          appBar: AppBar(
            title: Text('Device Center'),
          ),
          backgroundColor: Colors.white,
          body: Column(
            children: <Widget>[
              FlatButton(
                  onPressed: () async {
                    await getStatus();
                  },
                  child: Text('TEST STATUS')),
              FlatButton(
                  onPressed: () {
                    LedOn();
                    print('ON');
                  },
                  child: Text('LED ON')),
              FlatButton(
                  onPressed: () {
                    LedOFF();
                    print('OFF');
                  },
                  child: Text('LED OFF')),
              Switch(
                value: isSwitched,
                onChanged: (value) async {
                  await _handleSwitch(value);
                },
              ),
            ],
          )),
    );
  }
}
0 голосов
/ 10 июля 2020

Вы должны сделать что-то вроде этого:

  Widget _createSwitch(){
    if(isSwitched==null)
      return Center();
    return  Switch(
      value: isSwitched,
      onChanged: (value) {
        if (isSwitched == 'TRUE') {
          return LedOFF();
        } else {
          LedOn();
        }
      },
    );
  }

и изменить getStatus на это:

  void getStatus() async {
    bool mswitch = (await FirebaseDatabase.instance
            .reference()
            .child("DHT11/Device1/LED_STATUS/DATA")
            .once())
        .value;
    print(mswitch);
      setState(() {
         isSwitched=mswitch;
       });
  }
...