Thinking & coding: Turning 180° with the code, a good lesson learned.
In this session I wanted to bring the eventcard into the listview. And then also the data of the backend. After all this I want to clean up the code a bit.
I will still need a provider
Still, I want to somehow separate the FirestoreService from the UI. I wanted to do this by extracting the widgets in the FirestoreService. But then I will still need a provider, a stream provider. Maybe I will switch to a FutureProvider later. I am not yet sure of that. I want to use Riverpod because I need 2 providers of the same type.
I learned a good lesson
So this session I learned a good lesson. If I want to separate the UI and the logic or backend I always need stat management. So I have to restore my thinking to the original idea. This will certainly not be the last time I have to overthrow my code to achieve my goal. But don't worry, we're flying back in there.
A resume of what I have and should do.
- I have a Firestore service that reads the events from the backend.
- In the Firestore service I have placed an Event Model in such a way that this data is mapped in a list to the shape of my custom EventModel.
- Now I'm going to build a provider that will make this modeled list of data available to the UI.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | import 'package:firebase_core/firebase_core.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:my_first_production/widgets/my_app.dart'; void main() async { // Binding and initialising of Firebase in Flutter app WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp(); runApp( ProviderScope( child: MyApp(), ), ); } |
1 2 3 4 5 6 7 8 9 10 11 | import 'package:hooks_riverpod/all.dart'; import 'package:my_first_production/models/event_model.dart'; import 'package:my_first_production/services/firestore_event_service_next.dart'; final eventProvider = StreamProvider.autoDispose<List<Events>>( (ref) { final firestoreService = FirestoreEventServiceNext(); Stream<List<Events>> listOfEvents = firestoreService.getEvents(); return listOfEvents; }, ); |
Autodispose
At first I had some trouble adding ".autodispose" to my StreamProvider. But after the complete restart of the VSC, there was suddenly no problem anymore.
Test my state management
In the EventScreen I then have to test my state management. Implemented a simple Listview.builder. Why a listview.builder? Well according to the documentation, if you want to make a list with an unprecedented number of data elements, you have to use the builder. So read so done. At least I've already seen code on the net that uses a regular Listview.
In Code Line 14 I created my StreamProvider object.
In Code line 37 I wrote A Streambuilder who will prepare the data list of my Stream provider for use. With code line 41-46 catching a possible read error from the backend and a catch for while the stream is loading.
In Code Line 50 I then wrote a Listview.builder. Which will read and display my data from the backhand repeatedly, and this for the time being in a ListTile.
And as you can see, I can now use the data through my own EventModel variables.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/all.dart'; import 'package:my_first_production/models/event_model.dart'; import 'package:my_first_production/owner_data/owner_data.dart'; import 'package:my_first_production/providers/event_provider.dart'; class EventScreen extends HookWidget { const EventScreen({Key key}) : super(key: key); @override Widget build(BuildContext context) { Stream<List<Events>> lijstjes = useProvider(eventProvider.stream); return Container( decoration: BoxDecoration( //color: Colors.white, image: DecorationImage( image: AssetImage(eventScreenBackground), fit: BoxFit.fitWidth), ), child: Expanded( child: Scaffold( backgroundColor: Colors.transparent, body: Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox(height: 53), Container( padding: const EdgeInsets.only( left: leftPaddingNavigationScreenWidgets), child: Text( eventScreenTitle, style: Theme.of(context).textTheme.headline1, ), ), StreamBuilder<List<Events>>( stream: lijstjes, builder: (BuildContext context, AsyncSnapshot<List<Events>> snapshot) { if (snapshot.hasError) { return Text('Something went wrong'); } if (snapshot.connectionState == ConnectionState.waiting) { return Text("Loading"); } return Expanded( child: ListView.builder( itemCount: snapshot.data.length, itemBuilder: (context, index) { return ListTile( title: Text(snapshot.data[index].eventTitle), subtitle: Text(snapshot.data[index].eventDate), ); }, ), ); }) ], ), ), ), ); } } |
After a long toil and sweat, with a less friendly call here and there to every possible Saint, I managed to get the code working. Already in this preliminary test.
The next step will be to implement my already written own EventCard in the code. And to get a representation like in the prototype.
I hope you can follow my thinking a little bit, and that you understand why I took which steps. So I can do it too. So don't give up. It took me 12 hours to get all of this up and running without any errors.
If there are any errors in my code or mindset, please let me know in the comment section below this article.
Until the next
Do, believe and be happy,
Stefaan
A big thanks to Andy Julow, the architect of the snippets of code I used. I also followed his thinking process. Thank You Sir.
Also Thanks to Max Weber for the moral support.
Comments
Post a Comment