I am creating the List of Cards
according to the number of toDoId.
toDoController.toDo() is like
toDo = [q1, r4, g4, d4].obs;
And, this is my ListView.builder()
Obx(() {
List _todo = toDoController.toDo();
return ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemCount: _todo.length,
itemBuilder: (BuildContext context, int i) {
var _loading = true;
var _title = 'loading';
getTodoInfo() async {
_title = await toDoController
.getTodoInfo(
_todo[i]
);
_loading = false;
print(_title); // 'Clean!' <--- returns correct title
}
getTodoInfo();
return Container(
height: 150,
width: 150,
child: _loading
? Text(
_title,
)
: Text(
_title,
),
);
},
);
})
I am trying to make each Container calls the http requests
to get the title from my database. Get the title and then update to the Text()
widget below. However, it doesn't get updated after the value has been returned from the server.
I could make them wait for the request to get the title by using FutureBuilder
. I tried with FutureBuilder too. However, FutureBuilder was not also reactive to the variable
changes. So, I am trying to do this here. I kinda get the problem. After, the widget is returned, it is not changeable? Is there any way that I can do it with GetX?
Here's an example of using GetX with a Listview.builder.
This example uses a GetBuilder rather than Obx, as I'm not sure using a stream adds anything of benefit. If for some reason observables/streams are needed, numbers
can be updated to be an .obs
and the update()
calls should be removed and GetBuilder
replaced by GetX
or Obx
. If someone asks, I'll add that as an alternate example.
The GetBuilder wraps the ListView.builder and only the ListView will be rebuilt, not the entire widget tree / page.
import 'package:flutter/material.dart';
import 'package:get/get.dart';
class ListDataX extends GetxController {
List<int> numbers = List<int>.from([0,1,2,3]);
void httpCall() async {
await Future.delayed(Duration(seconds: 1),
() => numbers.add(numbers.last + 1)
);
update();
}
void reset() {
numbers = numbers.sublist(0, 3);
update();
}
}
class GetXListviewPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
ListDataX dx = Get.put(ListDataX());
print('Page ** rebuilt');
return Scaffold(
body: SafeArea(
child: Column(
children: [
Expanded(
flex: 8,
child: GetBuilder<ListDataX>(
builder: (_dx) => ListView.builder(
itemCount: _dx.numbers.length,
itemBuilder: (context, index) {
return ListTile(
title: Text('Number: ${_dx.numbers[index]}'),
);
}),
),
),
Expanded(
flex: 1,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
RaisedButton(
child: Text('Http Request'),
onPressed: dx.httpCall,
),
RaisedButton(
child: Text('Reset'),
onPressed: dx.reset,
)
],
)
)
],
),
),
);
}
}
Obx
/ Streams versionHere's the above solution using Rx
streams & Obx
widget.
class ListDataX2 extends GetxController {
RxList<int> numbers = List<int>.from([0,1,2,3]).obs;
void httpCall() async {
await Future.delayed(Duration(seconds: 1),
() => numbers.add(numbers.last + 1)
);
//update();
}
void reset() {
numbers = numbers.sublist(0, 3);
//update();
}
}
class GetXListviewPage2 extends StatelessWidget {
@override
Widget build(BuildContext context) {
ListDataX2 dx = Get.put(ListDataX2());
print('Page ** rebuilt');
return Scaffold(
body: SafeArea(
child: Column(
children: [
Expanded(
flex: 8,
child: Obx(
() => ListView.builder(
itemCount: dx.numbers.length,
itemBuilder: (context, index) {
return ListTile(
title: Text('Number: ${dx.numbers[index]}'),
);
}),
),
),
Expanded(
flex: 1,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
RaisedButton(
child: Text('Http Request'),
onPressed: dx.httpCall,
),
RaisedButton(
child: Text('Reset'),
onPressed: dx.reset,
)
],
)
)
],
),
),
);
}
}