使用 Flutter GetX 和 API,如何将 API 数据显示到 Text 小部件中?

时间:2021-07-24 13:56:24

标签: flutter api getx flutter-getx

我一直在观看 YouTube 视频并阅读如何使用 GetX 来显示 API 数据,但我无法让它与我的 API 一起使用。我无法弄清楚我缺少什么才能从我的 StockQuoteModel 显示股票价格。我试图将价格放入 ListView 的尾随部分,但不知道如何访问数据。

Picture of the App

main.dart

void main() async {
  await GetStorage.init();
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: HomePage(),
    );
  }
}

主页.dart

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final StockController sC = Get.put(StockController());
    final StockQuoteController sQC = Get.put(StockQuoteController());
    

    TextEditingController tEC = TextEditingController();
    return Scaffold(
      appBar: AppBar(
        title: Text('Add to List Practice'),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          Get.bottomSheet(
            Container(
              height: 150,
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                crossAxisAlignment: CrossAxisAlignment.center,
                children: [
                  Padding(
                    padding: const EdgeInsets.fromLTRB(100, 0, 100, 10),
                    child: TextField(
                      controller: tEC,
                      autofocus: true,
                      maxLines: 1,
                      autocorrect: false,
                      keyboardType: TextInputType.text,
                      textCapitalization: TextCapitalization.characters,
                      decoration: InputDecoration(
                        labelText: 'Add Stock',
                        border: OutlineInputBorder(
                          borderSide: BorderSide(
                            color: Colors.black87,
                          ),
                          borderRadius: BorderRadius.circular(10),
                        ),
                      ),
                      onSubmitted: (text) {
                        sC.stocks.add(Stock(symbol: tEC.text));
                        tEC.clear();
                        Get.back();
                      },
                    ),
                  ),
                  // SizedBox(height: 15),
                  ElevatedButton(
                    onPressed: () {
                      sC.stocks.add(Stock(symbol: tEC.text));
                      tEC.clear();
                      Get.back();
                    },
                    child: Text('Enter'),
                    style: ElevatedButton.styleFrom(
                      primary: Colors.blue,
                    ),
                  ),
                ],
              ),
            ),
            enableDrag: false,
            shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.only(
                  topLeft: Radius.circular(30.0),
                  topRight: Radius.circular(30.0)),
            ),
            backgroundColor: Colors.white,
          );
        },
        child: Icon(Icons.add),
      ),
      body: Container(
        child: Padding(
          padding: EdgeInsets.all(5),
          child: Obx(
            () => ListView.separated(
              itemCount: sC.stocks.length,
              separatorBuilder: (context, index) {
                return Divider(
                  color: Colors.black,
                  thickness: 0.1,
                  height: 0.0,
                );
              },
              itemBuilder: (context, index) {
                return Dismissible(
                  key: UniqueKey(),
                  direction: DismissDirection.endToStart,
                  onDismissed: (direction) {
                    sC.stocks.removeAt(index);
                  },
                  background: Container(
                    alignment: Alignment.centerRight,
                    padding: EdgeInsets.only(right: 20.0),
                    color: Colors.red,
                    child: Icon(
                      Icons.delete,
                      color: Colors.white,
                    ),
                  ),
                  child: ListTile(
                    leading: Text(
                      sC.stocks[index].symbol,
                    ),
                    trailing: Obx(() {
                      if (sQC.isLoading.value)
                        return Text('loading');
                      else
                        return Text(
                            sQC.stockQuote.price); // stuck here!
                    }),
                  ),
                );
              },
            ),
          ),
        ),
      ),
    );
  }
}

services.dart

class StockQuoteServices {
  static Future<StockQuote?> getStockQuote() async {
    String url =
        'https://www.alphavantage.co/query?function=GLOBAL_QUOTE&symbol=sq&apikey=***********';

    http.Response response;
    response = await http.get(Uri.parse(url));
    if (response.statusCode == 200) {
      StockQuote stockQuote = StockQuote.fromJson(json.decode(response.body));
      return stockQuote;
    } else {
      return null;
    }
  }
}

这是 api json

{
  "Global Quote": {
    "01. symbol": "SQ",
    "02. open": "261.8500",
    "03. high": "267.7700",
    "04. low": "261.2800",
    "05. price": "264.0000",
    "06. volume": "6374083",
    "07. latest trading day": "2021-07-23",
    "08. previous close": "260.5900",
    "09. change": "3.4100",
    "10. change percent": "1.3086%"
  }
}

controller.dart

class StockController extends GetxController {
  var stocks = [].obs;

  void add(Stock s) {
    stocks.add(s);
  }

  @override
  void onInit() {
    List? storedStocks = GetStorage().read<List>('stocks');
    if (storedStocks != null) {
      stocks = storedStocks.map((e) => Stock.fromJson(e)).toList().obs;
    }
    ever(stocks, (_) {
      GetStorage().write('stocks', stocks.toList());
    });
    super.onInit();
  }
}

class StockQuoteController extends GetxController {
  var isLoading = true.obs;
  var stockQuote = StockQuote().obs;

  @override
  void onInit() {
    getStockQuote();
    super.onInit();
  }

  void getStockQuote() async {
    try {
      isLoading(true);
      var quotes = await StockQuoteServices.getStockQuote();
      if (quotes != null) {
        stockQuote.value = quotes;
      }
    } finally {
      isLoading(false);
    }
  }
}

stockmodel.dart

class Stock {
  String symbol;

  Stock({required this.symbol});

  factory Stock.fromJson(Map<String, dynamic> json) =>
      Stock(symbol: json['symbol']);

  Map<String, dynamic> toJson() => {'symbol': symbol};
}

stockquotemodel.dart

class StockQuote {
  GlobalQuote? globalQuote;

  StockQuote({this.globalQuote});

  StockQuote.fromJson(Map<String, dynamic> json) {
    globalQuote = json['Global Quote'] != null
        ? new GlobalQuote.fromJson(json['Global Quote'])
        : null;
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    if (this.globalQuote != null) {
      data['Global Quote'] = this.globalQuote?.toJson();
    }
    return data;
  }
}

class GlobalQuote {
  String? symbol;
  String? open;
  String? high;
  String? low;
  String? price;
  String? volume;
  String? latestTradingDay;
  String? previousClose;
  String? change;
  String? changePercent;

  GlobalQuote(
      {this.symbol,
      this.open,
      this.high,
      this.low,
      this.price,
      this.volume,
      this.latestTradingDay,
      this.previousClose,
      this.change,
      this.changePercent});

  GlobalQuote.fromJson(Map<String, dynamic> json) {
    symbol = json['01. symbol'];
    open = json['02. open'];
    high = json['03. high'];
    low = json['04. low'];
    price = json['05. price'];
    volume = json['06. volume'];
    latestTradingDay = json['07. latest trading day'];
    previousClose = json['08. previous close'];
    change = json['09. change'];
    changePercent = json['10. change percent'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['01. symbol'] = this.symbol;
    data['02. open'] = this.open;
    data['03. high'] = this.high;
    data['04. low'] = this.low;
    data['05. price'] = this.price;
    data['06. volume'] = this.volume;
    data['07. latest trading day'] = this.latestTradingDay;
    data['08. previous close'] = this.previousClose;
    data['09. change'] = this.change;
    data['10. change percent'] = this.changePercent;
    return data;
  }
}

1 个答案:

答案 0 :(得分:0)

Krish Bhanushali 回答了。

我缺少价值。

sQC.stockQuote.value.globalQuote!.price as String 为我工作。

必须添加空检查和作为空安全的字符串。不确定这是否是最好的方法,但它有效。