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
I cannot see, where it is breaking at and no error shows up but my screen does not build.
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