Search code examples
flutterriverpodflutter-listview

Trying to build a ListView using Riverpod as state watcher


My goal is to have a ListView.builder, which updates, whenever the state changes. My state depends on a HTTP request. I manage to make my request successfully, I get a response and make it a List. For some reason, I do not get UI update on my screen and everything used to work, it got broken after trying to make the ListView build dynamically with the response.

So this is my main file, where I have added the provider scope:

void main() {
  runApp(const ProviderScope(child: MainApp()));
}

class MainApp extends StatelessWidget {
  const MainApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const ProviderScope(
        child:
            MaterialApp(debugShowCheckedModeBanner: false, home: MainPage()));
  }
}

And this is my main page:

class MainPage extends ConsumerWidget {
  const MainPage({super.key});

  @override
  Widget build(BuildContext context, ref) {
    // provider
    final data = ref.watch(roomDataProvider);

    final roomIDController = TextEditingController();
    // UI screen size
    Size size = MediaQuery.of(context).size;

    double deviceWidth = size.width;
    double deviceHeight = size.height;

    return Scaffold(
        backgroundColor: bluePrimary,
        body: data.when(
            data: (data) {
              List<RoomModel> roomList = data.map((room) => room).toList();
              SafeArea(
                  child: Container(
                padding:
                    const EdgeInsets.symmetric(horizontal: 36, vertical: 16),
                child: Column(
                    //crossAxisAlignment: CrossAxisAlignment.center,
                    children: [
                      Row(
                        mainAxisAlignment: MainAxisAlignment.spaceBetween,
                        children: [
                          IconButton(
                            iconSize: deviceWidth * 0.09,
                            icon: const Icon(Icons.person_outline,
                                color: orangePrimary),
                            onPressed: () {},
                          ),
                          IconButton(
                            icon: const Icon(
                              Icons.add,
                              color: orangePrimary,
                            ),
                            iconSize: deviceWidth * 0.09,
                            onPressed: () {
                              Navigator.push(
                                context,
                                MaterialPageRoute(
                                    builder: (context) =>
                                        const CreateRoomScreen()),
                              );
                            },
                          )
                        ],
                      ),
                      SizedBox(height: deviceHeight * 0.04),
                      Align(
                        alignment: Alignment.centerLeft,
                        child: Text("Watch",
                            style: TextStyle(
                                fontFamily: 'Chalet',
                                fontSize: deviceWidth * 0.12,
                                color: orangePrimary,
                                fontWeight: FontWeight.w300,
                                height: deviceHeight * 0.001)),
                      ),
                      Align(
                        alignment: Alignment.centerLeft,
                        child: Text("With",
                            style: TextStyle(
                                fontFamily: 'Chalet',
                                fontSize: deviceWidth * 0.12,
                                color: whitePrimary,
                                fontWeight: FontWeight.w300,
                                height: deviceHeight * 0.001)),
                      ),
                      Align(
                        alignment: Alignment.centerLeft,
                        child: Text("Me",
                            style: TextStyle(
                                fontFamily: 'Chalet',
                                fontSize: deviceWidth * 0.12,
                                color: orangePrimary,
                                fontWeight: FontWeight.w300,
                                height: deviceHeight * 0.001)),
                      ),
                      SizedBox(height: deviceHeight * 0.04),
                      Align(
                        alignment: Alignment.centerLeft,
                        child: Text("Join room",
                            style: TextStyle(
                                fontFamily: 'Chalet',
                                fontSize: deviceWidth * 0.07,
                                color: whitePrimary,
                                fontWeight: FontWeight.w100,
                                height: deviceHeight * 0.001)),
                      ),
                      SizedBox(height: deviceHeight * 0.008),

                      // email textField
                      SizedBox(
                        width: MediaQuery.of(context).size.width * 0.85,
                        child: TextField(
                          controller: roomIDController,
                          decoration: InputDecoration(
                              filled: true,
                              fillColor: whitePrimary,
                              border: OutlineInputBorder(
                                  borderRadius: BorderRadius.circular(12),
                                  borderSide: BorderSide.none),
                              hintText: 'Enter room ID to join it',
                              hintStyle: const TextStyle(
                                  color: Color.fromARGB(255, 174, 173, 173))),
                        ),
                      ),

                      SizedBox(height: deviceHeight * 0.016),

                      Align(
                        alignment: Alignment.bottomRight,
                        child: FloatingActionButton(
                          backgroundColor: orangePrimary,
                          child: const Icon(Icons.arrow_forward_ios_rounded,
                              color: whitePrimary),
                          onPressed: () {},
                        ),
                      ),

                      SizedBox(height: deviceHeight * 0.020),

                      Align(
                        alignment: Alignment.centerLeft,
                        child: Text("My rooms",
                            style: TextStyle(
                                fontFamily: 'Chalet',
                                fontSize: deviceWidth * 0.07,
                                color: whitePrimary,
                                fontWeight: FontWeight.w100,
                                height: deviceHeight * 0.001)),
                      ),

                      SizedBox(height: deviceHeight * 0.014),

                      // Display horizontal scroll rooms
                      Align(
                        alignment: Alignment.centerLeft,
                        child: SizedBox(
                          width: deviceWidth,
                          child: SizedBox(
                            height: deviceWidth * 0.56,
                            width: deviceWidth * 0.42,
                            child: ListView.builder(
                              scrollDirection: Axis.horizontal,
                              itemCount: roomList.length,
                              itemBuilder: (context, index) {
                                return Stack(children: [
                                  Container(
                                      height: deviceWidth * 0.8,
                                      width: deviceWidth * 0.42,
                                      margin: const EdgeInsets.symmetric(
                                          horizontal: 3),
                                      decoration: BoxDecoration(
                                          color: Colors.white,
                                          borderRadius:
                                              BorderRadius.circular(10)),
                                      child: ListTile(
                                        title: Text(roomList[index].uniqueID),
                                        subtitle:
                                            (Text(roomList[index].uniqueID)),
                                      )),
                                  InkWell(
                                    child: Container(
                                      height: deviceWidth * 0.4,
                                      width: deviceWidth * 0.42,
                                      margin: const EdgeInsets.symmetric(
                                          horizontal: 3),
                                      decoration: BoxDecoration(
                                          color: orangePrimary,
                                          borderRadius:
                                              BorderRadius.circular(10),
                                          boxShadow: const [
                                            BoxShadow(
                                                color: Colors.black,
                                                offset: Offset(0, 5),
                                                blurRadius: 10)
                                          ]),
                                      child: Image.asset(
                                          "assets/Logo.png"),
                                    ),
                                    onTap: () {},
                                  )
                                ]);
                              },
                            ),
                          ),
                        ),
                      )
                    ]),
              ));
              return null;
            },
            error: (err, s) => Text(err.toString()),
            loading: () => const Center(
                  child: CircularProgressIndicator(),
                )));
  }
}

and that is how the roomProvider looks like, it basically calls my http request there

final roomDataProvider = FutureProvider<List<RoomModel>>((ref) async {
  return ref.watch(roomProvider).getUserRooms();
});

The roomList looks as following enter image description here

I cannot see, where it is breaking at and no error shows up but my screen does not build.


Solution

  • In your code:

    return Scaffold(
            backgroundColor: bluePrimary,
            body: data.when(
                data: (data) {
                  List<RoomModel> roomList = data.map((room) => room).toList();
                  SafeArea( // --> This is the problem
    

    in the when case, you need to explicitly return:

    return SafeArea(...)
    

    without a return statement, it doesn't know what widget to display once it has the data