Search code examples
flutterlistviewtextfieldproviderdismissible

Looking for advice on implementing state to add/delete from a ListView


I am attempting to make my first app after numerous videos and courses. I have no prior experience in programming before this. Dart/Flutter is my first language and I am having trouble finishing the last steps on my app.

My first attempt I was able to add and delete stocks from the ListView.builder but I could not get the data from the api to work properly.

I figured out how to use the api the way I needed to but I couldn't get it to work with the way the app was built. So I completely redid the app to work with the api data, but now I cannot figure out how to add stocks with the TextField and remove them with Dismissible.

I hate to ask for help because I am trying to teach myself as I got but I have been stuck for 2 weeks since the ui was built. I've watched many videos and asked questions on Stack with no luck.

If anyone could show me how to implement the state management it would be greatly appreciated!

https://github.com/romajc84/my_stock_app.git


Solution

  • I checked the codebase, first of all great work for a starter! I have wrote few notes (I don't have the time to write a lot of things but you have to focus on architecture more).

    The dismissing functionality is done with simple Dismissible widget.

    I hate to ask for help because I am trying to teach myself as I got but I have been stuck for 2 weeks since the ui was built.

    Don't hate to ask ^_^. It's okay to ask, but your question should be focused and specific. You shouldn't expect people to search in your repo and fix your bugs. You have to show the code snippet you have question about, what you have tried, what you expect and what you get instead. And try to keep it one specific question per post.

    This way you will get the help you want.

    I only implemented the adding mechanism using ChangeNotifier like so:

    import 'dart:collection';
    
    import 'package:flutter/material.dart';
    import 'package:http/http.dart';
    
    import 'http_etf.dart';
    import 'http_stock.dart';
    
    class ProvModel extends ChangeNotifier {
      static const _defaultSymbols = ['t', 'aapl', 'tsla', 'amd', 'googl', 'spy'];
    
      final List<Stock> _symbols = [];
      final List<Etf> _etf = [];
      bool _adding = false;
    
      void fetchData() async {
        _fetchEtf().catchError(print);
        _fetchStocks().catchError(print);
      }
    
      Future<void> _fetchStocks() async {
        final stocks = await fetchStocks(_defaultSymbols, Client());
        _symbols.addAll(stocks);
        notifyListeners();
      }
    
      Future<void> _fetchEtf() async {
        final etf = await fetchEtf(Client());
        _etf.addAll(etf);
        notifyListeners();
      }
    
      UnmodifiableListView<Stock> get symbols => UnmodifiableListView(_symbols);
      UnmodifiableListView<Etf> get etf => UnmodifiableListView(_etf);
      bool get adding => _adding;
    
      void addSymbol(String newSymbol) async {
        _adding = true;
        notifyListeners();
        final stocks = await fetchStocks([newSymbol], Client());
        if (stocks == null || stocks.isEmpty) return;
        final stock = stocks.first;
        _symbols.add(stock);
        _adding = false;
        notifyListeners();
      }
    }
    

    I created a method dedicated to work once the app starts to start fetching the data for both the stocks and the etf, in the MyApp as following:

    import 'package:flutter/material.dart';
    import 'package:my_stock_app/prov_model.dart';
    import 'package:provider/provider.dart';
    import 'home_page.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return ChangeNotifierProvider(
          create: (context) => ProvModel()..fetchData(),
          child: MaterialApp(
            theme: ThemeData(
              primaryColor: Colors.black,
              textTheme: TextTheme(
                bodyText2: TextStyle(
                  color: Colors.white,
                ),
              ),
            ),
            home: HomePage(),
          ),
        );
      }
    }
    

    I tried to refactor the code a bit. Here's the functioning project: Repository

    Keep it up and keep learning!