пытаюсь отобразить значение моей переменной, но вывод равен нулю

#android #flutter

#Android #флаттер

Вопрос:

Я делаю проект в Flutter, в котором я получаю скорость передачи данных в реальном времени с помощью API, и я получаю свою скорость, но не могу отобразить на своем экране, что она равна нулю ..! код ниже:

 import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'coin_data.dart';
import 'dart:io' show Platform;
import 'networking.dart';

class PriceScreen extends StatefulWidget {
  @override
  _PriceScreenState createState() => _PriceScreenState();
}

class _PriceScreenState extends State<PriceScreen> {
  BitNetwork bitNetwork = BitNetwork('$BitCoinURL/BTC/USD?apikey=$BitCoinKey');
  int bitRate;

  void getCurrentBitRate() async {
    dynamic bitData = await bitNetwork.getData();
    double temp = bitData['rate'];
    bitRate = temp.toInt();
    print(bitRate);
  }

  String selectedCurrency = 'USD';`enter code here`

  @override
  Widget build(BuildContext context) {
    getCurrentBitRate();
    return Scaffold(
      appBar: AppBar(
        title: Text('Coin Ticker'),
      ),`enter code here`
      body: Column(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: <Widget>[
          Padding(
            padding: EdgeInsets.fromLTRB(18.0, 18.0, 18.0, 0),
            child: Card(
              color: Colors.lightBlueAccent,
              elevation: 5.0,
              shape: RoundedRectangleBorder(
                borderRadius: BorderRadius.circular(10.0),
              ),
              child: Padding(
                padding: EdgeInsets.symmetric(vertical: 15.0, horizontal: 28.0),
                child: Text(
                  '1 BTC = $bitRate USD',
                  textAlign: TextAlign.center,
                  style: TextStyle(
                    fontSize: 20.0,
                    color: Colors.white,
                  ),
                ),
              ),
            ),
          ),
          Container(
              height: 150.0,
              alignment: Alignment.center,
              padding: EdgeInsets.only(bottom: 30.0),
              color: Colors.lightBlue,
              child: Platform.isIOS ? iOSPicker() : androidDropdown()),
        ],
      ),
    );
  }
} 
 

ответ в консоли:
I / flutter (14181): 47131
I / flutter (14181): 47131
I / flutter (14181): 47129

вывод на экран = 1 BTC = null USD. => ????

Ответ №1:

Вам нужно дождаться загрузки валюты, оберните свой виджет в FutureBuilder :

 Future<int> getCurrentBitRate() async {
  dynamic bitData = await bitNetwork.getData();
  double temp = bitData['rate'];
  return temp.toInt();
}

// build method
child: FutureBuilder<int>(
  future: getCurrentBitRate(),
  builder (context, snapshot) {
    if (snapshot.hasData) {
      final bitRate = snapshot.data;
      return Column(
        // Your column here.
      );
    }
    return CircularProgressIndicator();
  }
),
 

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

Ответ №2:

Проблема в том, что вы не ожидаете getCurrentBitRate(), и вы также вызываете его в своем методе сборки. В методе сборки должен быть только код пользовательского интерфейса. Что я рекомендую вам сделать, так это переопределить initState() и вызвать его там (все еще не могу его дождаться, но он будет вызван перед сборкой);

 @override
initState(){
  getCurrentBitRate();
  super.initState();
}
 

Это поможет решить вашу проблему, но это не лучшее решение. Я рекомендую посмотреть учебные пособия по какой-либо внешней системе управления состоянием, такой как BLoC, Provider и / или RxDart. Это значительно упростит отладку подобных ситуаций.

Ответ №3:

bitRate Значение null связано с тем, что вы вызываете его в build функции, а ваш метод getCurrentBitRate() является async методом, что означает, что метод будет ждать получения значения, но до тех пор ваш build метод уже завершит рендеринг виджетов с bitRate сохранением значения null .

Есть несколько способов исправить это, но я бы порекомендовал следующий:

Вызовите свой метод getCurrentBitRate() в initState методе и удалите его из build функции, так как это первый метод, который запускается в вашем виджете и используется setState , чтобы обновленное значение bitRate отображалось в вашем виджете.

 class _PriceScreenState extends State<PriceScreen> {
  BitNetwork bitNetwork = BitNetwork('$BitCoinURL/BTC/USD?apikey=$BitCoinKey');
  int bitRate;

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

    getCurrentBitRate(); // Call it in initState amp; use setState
  }

  void getCurrentBitRate() async {
    dynamic bitData = await bitNetwork.getData();
    double temp = bitData['rate'];
    bitRate = temp.toInt();
    print(bitRate);
    if (mounted) {  // <--- mounted property checks whether your widget is still present in the widget tree
      setState((){}); // Will update the UI once the value is retrieved
    }
  }

  String selectedCurrency = 'USD';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Coin Ticker'),
      ),`enter code here`
      body: Column(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: <Widget>[
          Padding(
            padding: EdgeInsets.fromLTRB(18.0, 18.0, 18.0, 0),
            child: Card(
              color: Colors.lightBlueAccent,
              elevation: 5.0,
              shape: RoundedRectangleBorder(
                borderRadius: BorderRadius.circular(10.0),
              ),
              child: Padding(
                padding: EdgeInsets.symmetric(vertical: 15.0, horizontal: 28.0),
                child: Text(
                  '1 BTC = $bitRate USD',
                  textAlign: TextAlign.center,
                  style: TextStyle(
                    fontSize: 20.0,
                    color: Colors.white,
                  ),
                ),
              ),
            ),
          ),
          Container(
              height: 150.0,
              alignment: Alignment.center,
              padding: EdgeInsets.only(bottom: 30.0),
              color: Colors.lightBlue,
              child: Platform.isIOS ? iOSPicker() : androidDropdown()),
        ],
      ),
    );
  }
} 
 

Ответ №4:

Это значение равно нулю, потому что при build() вызове getCurrentBitRate() оно еще не завершило свою работу.

Для этих операций FutureBuilder это один из лучших виджетов. Ему просто нужно a future и a builder , чтобы объявить, что делать после получения данных.

 // CHANGE TO FUTURE STYLE
Future<Int> getCurrentBitRate() async {
  dynamic bitData = await bitNetwork.getData();
  double temp = bitData['rate'];
  bitRate = temp.toInt();
  print(bitRate);
  return bitRate;
}
 

Затем измените структуру сборки на это

  // DECLARE A FUTURE FOR getCurrentBitRate()
 Future _future;

 initState(){
   _future = await getCurrentBitRate();
   super.initState();
 }

 @override
 Widget build(BuildContext context) {
   // getCurrentBitRate(); REMOVE THIS LINE
   return FutureBuilder(
     future: _future,
     builder: (context, snapshot) {
       if(snapshot.hasData){

         // YOUR DATA IS READY
         double temp = snapshot.data['rate'];
         
         // JUST CONTINUE REST OF ORIGINAL CODE BELOW 
         return Scaffold(
           appBar: AppBar(
           title: Text('Coin Ticker'),
           ),
           ...
       }
     }
   );