How can i use refresh indicator without stateful widget using getx or provider , i use it in my code but when i update my api data and refresh from my app and it's not showing new updated data inside futurebuilder listview after refresh
give me some solution code for refresh data using stateless widget and provider
Thanks In advance
Hi @tonmooy, you can use the new GetX mixin called StateMixin. See an example below:
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:dio/dio.dart';
void main() {
runApp(GetMaterialApp(
initialRoute: '/home',
getPages: [
GetPage(
name: '/home',
page: () => HomePage(),
),
GetPage(
name: '/city',
page: () => CityPage(),
binding: CityBinding(),
),
],
));
}
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('HOME')),
body: Center(
child: RaisedButton(
onPressed: () => Get.toNamed('/city'),
child: Text('Go to Cities'),
),
),
);
}
}
class CityBinding extends Bindings {
@override
void dependencies() {
Get.put(Dio());
Get.put(CityController(dio: Get.find()));
}
}
class CityModel {
CityModel({
this.abbreviation,
this.name,
});
String abbreviation;
String name;
factory CityModel.fromJson(Map<String, dynamic> json) => CityModel(
abbreviation: json["sigla"],
name: json["nome"],
);
static List<CityModel> listFromJson(list) =>
List<CityModel>.from(list.map((x) => CityModel.fromJson(x)));
}
class CityController extends GetxController with StateMixin<List<CityModel>> {
final Dio dio;
CityController({this.dio});
@override
void onInit() {
findAllCities();
super.onInit();
}
findAllCities() {
const String url = 'https://servicodados.ibge.gov.br/api/v1/localidades/estados';
dio.get(url).then((result) {
List<CityModel> data = CityModel.listFromJson(result.data);
change(data, status: RxStatus.success());
}, onError: (err) {
change(null, status: RxStatus.error(err.toString()));
});
}
}
class CityPage extends GetView<CityController> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Cities')),
body: Container(
child: controller.obx(
(state) => ListView.builder(
itemCount: state.length,
itemBuilder: (context, index) {
return Text(state[index].name);
},
),
onLoading: Center(child: CircularProgressIndicator()), // optional
onError: (error) => Center( // optional
child: Text('Error: $error',
style: TextStyle(fontSize: 18),
textAlign: TextAlign.center,
),
),
),
),
);
}
}
@eduardoflorence i am reading the example about the proper use of stateMixin but why you link the mixin with the list... StateMixin> and when it became in a observable variable? maybe u can give us more explanation about it in documentation with some examples (streams and most recently GetStream)
@alvincast, this is the "magic" of GetX. I'm just kidding.
I am a contributor to this framework, but @jonataslaw is responsible for this feature. I confess that it also took me a while to understand how StateMixin works so amazingly.
Regarding your question, I linked to a list because my API returns a list. If my API returned only one city, I would link with CityModel only: StateMixin<CityModel>.
I will try to explain StateMixin in a simple way:
First, this:
class CityController extends GetxController with StateMixin<List<CityModel>> {
// ...
}
It is the same as:
class CityController extends GetxController {
final list = List<CityModel>>().obs;
//...
}
So you don't need to create an obs. StateMixin creates internally for you.
Second, this:
dio.get(url).then((result) {
List<CityModel> data = CityModel.listFromJson(result.data);
change(data, status: RxStatus.success());
}
it is the same as:
final loading = false.obs;
//...
loading.value = true;
dio.get(url).then((result) {
List<CityModel> data = CityModel.listFromJson(result.data);
list.assignAll(data);
loading.value = false;
}
that is, you no longer need a boolean variable to control the loading of your API and change updates List<CityModel> automatically.
Finally, in View, the new widget obx (not to be confused withObx), which is injected into the controller by StateMixin, listens to all changes made by change
thanks a lot maybe jonatas change the name of the new widget "obx" that can be confused for something like obxStateMix(?, now i can use StateMixin and declare multiples observables inside that controller so how it will work the obx? because as i see in your example controller.obx(
(state) => ListView.builder(
itemCount: state.length,
itemBuilder: (context, index) {
return Text(state[index].name);
},
),
...
the state is take as a list.,.(maybe for this StateMixin> ) but as i said in case u have multiples observables... thanks for ur answer
As far as I could understand, StateMixin should be used for use cases where we need to control only one state that will be obtained asynchronously (API query, for example) and for multiple observables continue using GetxController and GetX/GetBuilder/Obx.
thanks for the explanation
@alvincast and @tonmooy. can we close this issue?
yep
There are many cases where we need to call multiple API call in a single screen, but can't find any way to use multiple StateMixin in a single Controller.
Most helpful comment
@alvincast, this is the "magic" of GetX. I'm just kidding.
I am a contributor to this framework, but @jonataslaw is responsible for this feature. I confess that it also took me a while to understand how
StateMixinworks so amazingly.Regarding your question, I linked to a list because my API returns a list. If my API returned only one city, I would link with CityModel only:
StateMixin<CityModel>.I will try to explain StateMixin in a simple way:
First, this:
It is the same as:
So you don't need to create an obs.
StateMixincreates internally for you.Second, this:
it is the same as:
that is, you no longer need a boolean variable to control the loading of your API and
changeupdatesList<CityModel>automatically.Finally, in View, the new widget
obx(not to be confused withObx), which is injected into the controller by StateMixin, listens to all changes made bychange