jsonflutterdartriverpod

Flutter App hangs at build: Loading a Json Asset and Using Riverpod


I will try to be brief and only add relevant pieces of code. This is the screen that tries to load Item objects from a JSON:

Widget _buildItemList(List<Item> currentItemList) {
return ListView.builder(
    scrollDirection: Axis.vertical,
    shrinkWrap: true,
    itemCount: currentItemList.length,
    itemBuilder: (BuildContext context, int index) {
      return GestureDetector(
          onTap: () {
            Navigator.push(context, MaterialPageRoute(
              builder: (context) {
                return ItemDetailsPage(
                    item: currentItemList[index]);
              },
            ));
          },
          child: Text(currentItemList[index].productName)
      );
    }
);

}

Future<List<Item>> fetchItems() {

    final inventoryService = ref.watch(serviceProvider);
            Future<List<Item>> items = inventoryService.fetchData();  
return items;
}  

_futureBuilder() {
    return FutureBuilder<List<Item>>(
        future: fetchItems(),
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.done) {
            loading = false;
            final result = snapshot.data;
            if (result is Error) {
              const errorMessage = 'Problems getting data';
              return const Center(
                child: Text(
                  errorMessage,
                  textAlign: TextAlign.center,
                  style: TextStyle(fontSize: 18.0),
                ),
              );
            }
            return _buildItemList(result!);
          }
          else {
            return const SliverFillRemaining(
                child: Center(
                  child: CircularProgressIndicator(),
                ),
              );

          }
        }
    );
  }

This is the service provider for the fetchData function and also a serviceProvider that starts on main.

Future loadItems() async {
var jsonString = await rootBundle.loadString('assets/inventorylist.json');
inventoryResult =
InventoryResult.fromJson(jsonDecode(jsonString));

}

@override
  Future<List<Item>> fetchData() async {
    _currentItems = inventoryResultsToItems(inventoryResult) as Future<List<Item>>;
    return _currentItems ?? Future.error('No data found');
  }

Lastly this is Main.app. Since Flutter never loads I suppose I am creating a non-responding race condition of sorts.

    Future<void> main() async {
  //RUNAPP FOR RIVERPOD IMPLEMENTATION
  final service = await JsonInventoryService.create(); //runs loadItems()
  runApp(ProviderScope(overrides: [
    serviceProvider.overrideWithValue(service),
  ], child: const MyApp()));
  //runApp(const MyApp());
}

This results in phone emulator being stuck on Flutter logo indefinitely. I know my mistakes are simple as I just started learning Flutter last month but any help appreciated.


Solution

  • Some corrections as suggested by the comments. Instead of fetching the data from FutureBuilder, added this in the beginning of the main class:

    class _InventoryScreenState extends ConsumerState<InventoryScreen> {
      final inventoryService = ref.watch(serviceProvider);
      Future<List<Item>> currentItemList = inventoryService.fetchData();
    

    Now the ref was not being recognized from under the class directly.

    The instance member 'ref' can't be accessed in an initializer. 
    

    Was not getting an error inside fetchData() function. I added a late keyword which fixed this. Another error was that I forgot to add this json file to my /assets folder.