0

I have been watching YouTube videos and reading how to use GetX to display API data but I cannot get it to work with my API. I cannot figure out what I am missing to be able to display the price of a stock from my StockQuoteModel. I am attempting to put the price into the trailing section of my ListView but do not know how to access the data.

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(),
    );
  }
}

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;
    }
  }
}

This is the 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;
  }
}
romajc
  • 19
  • 1
  • 6

1 Answers1

1

Krish Bhanushali answered it.

I was missing value.

sQC.stockQuote.value.globalQuote!.price as String worked for me.

Had to add the null check and as String for null safety. Not sure if this was the best way but it works.

romajc
  • 19
  • 1
  • 6