Skip to content

Instantly share code, notes, and snippets.

@manikantag
Last active September 24, 2021 17:19
Show Gist options
  • Select an option

  • Save manikantag/18a0cab5ea2423e321aae62e50a3e00d to your computer and use it in GitHub Desktop.

Select an option

Save manikantag/18a0cab5ea2423e321aae62e50a3e00d to your computer and use it in GitHub Desktop.
Flutter Getx observable assignment in async issue
import 'package:flutter/material.dart';
import 'package:get/get.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
runApp(GetMaterialApp.router(
title: 'Test',
initialBinding: BindingsBuilder.put(() => AuthService(), permanent: true),
getPages: [
GetPage(
name: '/',
page: () => const LoginScreen(),
binding: BindingsBuilder.put(() => LoginController()),
),
GetPage(
name: '/home',
page: () => const HomeScreen(),
binding: BindingsBuilder.put(() => HomeController()),
),
],
));
}
class AppUser {
final String uid;
final String mobile;
int count = 0;
AppUser({required this.uid, required this.mobile});
AppUser.newUser(String uid, String mobile) : this(uid: uid, mobile: mobile);
AppUser.dummyUser() : this(uid: '', mobile: '');
@override
String toString() {
return {'mobile': mobile, 'uid': uid, 'counter': count}.toString();
}
}
// ----- models -----
class Doctor extends AppUser {
final String? regId;
Doctor({required String uid, required String mobile, this.regId})
: super(uid: uid, mobile: mobile);
Doctor.newDoctor(String uid, String mobile) : this(mobile: mobile, uid: uid);
}
class Patient extends AppUser {
final String? bmi;
Patient({required String uid, required String mobile, this.bmi})
: super(uid: uid, mobile: mobile);
Patient.newPatient(String uid, String mobile) : this(uid: uid, mobile: mobile);
}
// ----- Auth service -----
class AuthService extends GetxController {
Rx<bool> isAuthenticated = false.obs;
Rx<int> authCounter = 0.obs;
Rx<AppUser> currentUser = Rx(AppUser.dummyUser());
/* @override
void onInit() {
currentUser = Patient.newPatient('patient1', 'patientm1').toRx();
super.onInit();
} */
void doPatientLogin() async {
isAuthenticated.value = true;
// currentUser = Patient.newPatient('Patient_1', 'Patient_mobile_1').toRx();
currentUser = await Future.delayed(
const Duration(milliseconds: 10),
() => Patient.newPatient('Patient_1', 'Patient_mobile_1').obs,
);
print(currentUser);
}
void doDoctorLogin() async {
isAuthenticated.value = true;
// currentUser = Doctor.newDoctor('Doc_1', 'Doc_mobile_1').toRx();
currentUser = await Future.delayed(
const Duration(milliseconds: 10),
() => Doctor.newDoctor('Doc_1', 'Doc_mobile_1').obs,
);
print(currentUser);
}
void doLogout() {
isAuthenticated.value = false;
authCounter = 0.obs;
// tempCounter = Patient.newPatient('p2', 'm2').toRx();
// currentUser = Doctor.newDoctor('doctor1', 'docm1').toRx();
Get.rootDelegate.offNamed('/');
// Get.reset();
// Get.reloadAll(force: true);
// Get.reload<AuthService>();
// Get.deleteAll(force: true);
}
}
// ----- Login controller & page -----
class LoginController extends GetxController {
final authService = Get.find<AuthService>();
bool isLoggedin() => authService.isAuthenticated.value == true;
void doDoctorLogin() {
authService.doDoctorLogin();
Get.rootDelegate.offNamed('/home');
}
void doPatientLogin() {
authService.doPatientLogin();
Get.rootDelegate.offNamed('/home');
}
}
class LoginScreen extends GetView<LoginController> {
const LoginScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Obx(
() => controller.isLoggedin()
? const Text('Already logged in -> Logout (state not cleared)')
: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('authCounter: ${controller.authService.authCounter.value}'),
ElevatedButton(
onPressed: controller.doDoctorLogin,
child: const Text('Doctor Login'),
),
ElevatedButton(
onPressed: controller.doPatientLogin,
child: const Text('Patient Login'),
),
],
),
),
),
);
}
}
// ----- Home controller & page -----
class HomeController extends GetxController {
final AuthService _authService = Get.find<AuthService>();
final Rx<int> homeCounter = 0.obs;
late final Rx<int> authCounter;
late final Rx<AppUser> currentUser;
@override
void onInit() {
authCounter = _authService.authCounter;
currentUser = _authService.currentUser;
super.onInit();
}
void increment() {
homeCounter.value++;
authCounter.value++;
currentUser.value.count++;
}
void logout() => _authService.doLogout();
}
class HomeScreen extends GetView<HomeController> {
const HomeScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Obx(
() => Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Auth counter: ${controller.authCounter.value}'),
Text('Home counter: ${controller.homeCounter.value}'),
Text(
'Current User: ${controller.currentUser.value is Doctor ? 'Doctor' : 'Patient'}'),
Text('Current User: ${controller.currentUser.value}'),
ElevatedButton(
onPressed: controller.increment,
child: const Text('Increment counters'),
),
ElevatedButton(
onPressed: controller.logout,
child: const Text('Logout'),
),
],
),
),
),
);
}
}
@manikantag
Copy link
Author

manikantag commented Sep 24, 2021

Fix is to add await at line 112 & 117.

  void doTeacherLogin() async {
    await authService.doTeacherLogin();
    Get.rootDelegate.offNamed('/home');
  }

  void doStudentLogin() async {
    await authService.doStudentLogin();
    Get.rootDelegate.offNamed('/home');
  }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment