Reputation: 49
i am new in flutter/dart and i'm trying to build an app with an observer to redirect user for sign in if it wasn't done
Here is my code
class ControlView extends GetWidget<AuthViewModel>{
@override
Widget build(BuildContext context) {
ControlViewModel ctrlvwmdl = ControlViewModel();
return Obx(() {
return (Get.find<AuthViewModel>().user == null)
? LoginView()
: GetBuilder<ControlViewModel>(
builder: (controller) => Scaffold(
body: controller.currentScreen,
bottomNavigationBar: bottomNavigationBar(),
),
);
});
}
Widget bottomNavigationBar() {
return GetBuilder<ControlViewModel>(
init: ControlViewModel(),
builder: (controller) => BottomNavigationBar(
items: [
BottomNavigationBarItem(
icon: Icon(Icons.search), label: 'search'.tr),
BottomNavigationBarItem(
icon: Icon(Icons.home_outlined), label: 'reserve'.tr),
BottomNavigationBarItem(
icon: Icon(Icons.add), label: 'Déposer'),
BottomNavigationBarItem(
icon: Icon(Icons.email_outlined), label: 'Messages'),
BottomNavigationBarItem(
icon: Icon(Icons.person_outline), label: 'Profil'),
],
currentIndex: controller.navigatorValue,
onTap: (index) {
controller.changeSelectedValue(index);
},
//elevation: 0,
//selectedItemColor: Colors.black,
type: BottomNavigationBarType.fixed,
backgroundColor: Colors.yellow,
iconSize: 20,
),
);
}
}
My AuthViewModel
class is below
class AuthViewModel extends GetxController {
FirebaseAuth _auth = FirebaseAuth.instance;
String? email, password, name;
Rxn<User> _firebaseUser = Rxn<User>();
String? get user => _firebaseUser.value?.email;
@override
void onInit() {
// TODO: implement onInit
super.onInit();
_firebaseUser.bindStream(_auth.authStateChanges());
}
@override
void onReady() {
// TODO: implement onReady
super.onReady();
}
@override
void onClose() {
// TODO: implement onClose
super.onClose();
}
void googleSignInMethod() async {
print(">> Google Sign In");
GoogleSignIn googleSignIn = GoogleSignIn(scopes: ['email']);
final GoogleSignInAccount? googleUser = await googleSignIn.signIn();
print(">> google user : $googleUser");
GoogleSignInAuthentication googleSignInAuthentication =
await googleUser!.authentication;
final AuthCredential googleCredential = GoogleAuthProvider.credential(
idToken: googleSignInAuthentication.idToken,
accessToken: googleSignInAuthentication.accessToken,
);
await _auth.signInWithCredential(googleCredential).then((user) {
print(">> app user : $user");
});
}
void facebookSignInMethod() async {
print(">> Facebook Sign In");
FacebookLogin facebookSignIn = new FacebookLogin();
final FacebookLoginResult result = await facebookSignIn.logIn(['email']);
print(">> facebook result : $result");
switch (result.status) {
case FacebookLoginStatus.loggedIn:
final FacebookAccessToken accessToken = result.accessToken;
final facebookAuthCredential =
FacebookAuthProvider.credential(accessToken.token);
await _auth.signInWithCredential(facebookAuthCredential).then((user){
print(">> app user : $user");
});
break;
case FacebookLoginStatus.cancelledByUser:
print(">> User cancelled login with FaceBook account");
break;
case FacebookLoginStatus.error:
print(">> Error when login with FaceBook account");
break;
}
}
void signInWithEmailAndPassword() async {
try {
print(">> email $email");
print(">> password $password");
await _auth
.signInWithEmailAndPassword(email: email!, password: password!)
.then((value) {
print(">> value $value");
});
} catch (err) {
print(err.toString());
Get.snackbar(
'Error login account',
err.toString(),
colorText: Colors.black,
snackPosition: SnackPosition.BOTTOM,
);
}
}
}
And here is my main.dart
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GetMaterialApp(
title: 'Flutter App',
theme: ThemeData(
primarySwatch: Colors.blue,
appBarTheme: AppBarTheme(
color: Colors.orange
),
),
initialBinding: Binding(),
home: Scaffold(
appBar: AppBar(
title: Text('Training App'),
centerTitle: true,
actions: <Widget>[
IconButton(
icon: Icon(
Icons.settings,
color: Colors.white,
),
onPressed: () {
debugPrint('Settings button tapped');
},
),
IconButton(
icon: Icon(
Icons.more_horiz,
color: Colors.white,
),
onPressed: () {
debugPrint('Menu button tapped');
},
)
],
),
drawer: SideBar(),
body: ControlView(),
),
translations: Translate(),
locale: Locale('fr'), //Default language
fallbackLocale: Locale('fr'), //Default language in case of error
);
}
}
I'm getting the strange behavior below:
Another exception was thrown: Null check operator used on a null value
and I get this ugly screen:
without signin out, i performed a hot reload and i got the same error with a new hint in addition, it says
══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY╞═══════════════════════════════════════════
The following _CastError was thrown building Obx(has builder, state: _ObxState#37426): Null check operator used on a null value
The relevant error-causing widget was: Obx Obx:file:///C:/Users/yoozer/StudioProjects/swim_test/lib/view/control_view.dart:14:12
Here is the stack when the exception was thrown
The relevant error-causing widget was: Obx Obx:file:///C:/Users/yoozer/StudioProjects/swim_test/lib/view/control_view.dart:14:12
When the exception was thrown, this was the stack: #0 GetBuilderState.initState (package:get/get_state_manager/src/simple/get_state.dart:134:40) #1 StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:4805:57) #2 ComponentElement.mount (package:flutter/src/widgets/framework.dart:4638:5) #3 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3673:14) #4 Element.updateChild (package:flutter/src/widgets/framework.dart:3422:20) #5 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4690:16) #6 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4840:11) #7 Element.rebuild (package:flutter/src/widgets/framework.dart:4355:5) #8 StatefulElement.update (package:flutter/src/widgets/framework.dart:4872:5) #9 Element.updateChild (package:flutter/src/widgets/framework.dart:3412:15) #10 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4690:16) #11 GetWidgetCacheElement.performRebuild (package:get/get_state_manager/src/simple/get_widget_cache.dart:35:11) #12 Element.rebuild (package:flutter/src/widgets/framework.dart:4355:5) #13 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2620:33) #14 WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:882:21) #15 RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:319:5) #16 SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1143:15) #17 SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1080:9) #18 SchedulerBinding.scheduleWarmUpFrame. (package:flutter/src/scheduler/binding.dart:863:7) (elided 4 frames from class _RawReceivePortImpl, class _Timer, and dart:async-patch)
I spent long days troubleshooting the error and trying to understand what happen, I looked on the internet for a solution, a similar problem or a way to deeply inspect this behavior but i'm still stuck.
Any help will be welcome I will be very grateful
Upvotes: 1
Views: 4477
Reputation: 49
I looked for more. the error came from the fact that I did not fill in this property for the GetBuilder
init: ControlViewModel(),
Doing it correct the problem even with the first version of the code.
Upvotes: 2
Reputation: 49
i finally found the solution. Using the flutter dev tools for debugging, i noticed that the GetBuilder returned by the Obx((){}) inline function wasn't instantiated each time the error occurred. So i created a GetBuilder variable in the top of the build() method, and i instantiated it. Then in the Obx((){}) inline function i modified my code to return the object i instantiated above.
here is the only modification i made in the code, other classes and functions didn't change:
class ControlView extends GetWidget<AuthViewModel>{
@override
Widget build(BuildContext context) {
LoginView loginView = LoginView();
//ControlViewModel ctrlvwmdl = ControlViewModel();
GetBuilder<ControlViewModel> getbuilder = GetBuilder<ControlViewModel>(
init: ControlViewModel(),
builder: (controller) => Scaffold(
body: controller.currentScreen,
bottomNavigationBar: bottomNavigationBar(),
),
);
print(">> ControlView.build() : new call of the method.");
return Obx(() {
return (Get.find<AuthViewModel>().user == null)
? loginView
: getbuilder;
});
}
}
Upvotes: 0
Reputation: 81
[Null check operator used on a null value] error means that a (!), Which was used to check if a certain value/parameter is null, received a null value before it, therefore it performed it's functionality and caused a big error.
I don't have all of your code, but I think that the problem could be caused by one of two lines in the included pictures.
If not, then at everyplace where you use the Null check operator(!) You should do the following:
Bottom line, don't let any value reach a Null-check operator(!) While being null.
Upvotes: 0