I am trying to login with cubit and api So i did every thing and the model of login so when I click on login there are 2 errors shows to me 1- Null check operator used on a null value and this one shows when I make the login model variable ? and the second one when I sit the login model late 2- LateInitializationError: Field 'loginModel' has not been initialized.
this is my cubit
// ignore_for_file: avoid_print
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:sa/cubit/login_cubit/login_states.dart';
import 'package:sa/modules/login_model/login_model.dart';
import 'package:sa/network/dio_helper/dio_helper.dart';
import 'package:sa/network/end_points.dart';
import 'package:sa/styles/color/color.dart';
class LoginCubit extends Cubit<LoginStates> {
LoginCubit() : super(LoginInitislState());
static LoginCubit get(context) => BlocProvider.of(context);
var suffix = Icon(Icons.visibility_outlined, color: defaultColor);
bool isPassword = false;
void changeVisibilty() {
isPassword = !isPassword;
if (isPassword == false) {
suffix = Icon(Icons.visibility_off_outlined, color: defaultColor);
} else {
suffix = Icon(Icons.visibility_outlined, color: defaultColor);
}
emit(LoginChangeIconState());
}
LoginModel? loginModel;
void userData({
required email,
required password,
}) {
emit(LoginLoadingInitialStat());
DioHelper.postData(
url: LOGIN,
data: {
'email': email,
'password': password,
},
).then((value) {
loginModel = LoginModel.fromJson(value.data);
print('message is ${loginModel!.message!}');
print('Your token is ${loginModel!.data!.token!}');
print('login done');
emit(LoginSuccessState(loginModel!));
}).catchError((error) {
emit(LoginFailedState(error.toString()));
print('error when login in cubit ${error.toString()}');
});
}
}
and this is my states
import 'package:sa/modules/login_model/login_model.dart';
abstract class LoginStates{}
class LoginInitislState extends LoginStates{}
class LoginChangeIconState extends LoginStates{}
class LoginLoadingInitialStat extends LoginStates{}
class LoginSuccessState extends LoginStates
{
final LoginModel loginModel;
LoginSuccessState(this.loginModel);
}
class LoginFailedState extends LoginStates{
final String error;
LoginFailedState(this.error);
}
and this is the design of the login page
// ignore_for_file: must_be_immutable, avoid_print
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:sa/cubit/login_cubit/login_cubit.dart';
import 'package:sa/cubit/login_cubit/login_states.dart';
import 'package:sa/network/cache_helper/cache_helper.dart';
import 'package:sa/network/components/component.dart';
import 'package:sa/styles/color/color.dart';
class LoginScreen extends StatelessWidget {
LoginScreen({super.key});
var emailController = TextEditingController();
var passwordController = TextEditingController();
var formKey = GlobalKey<FormState>();
@override
Widget build(BuildContext context) {
return BlocConsumer<LoginCubit, LoginStates>(
listener: (context, state) {
if (state is LoginSuccessState) {
if (state.loginModel.status!) {
print(state.loginModel.message);
print(state.loginModel.status);
CachceHelper.saveData(
key: 'token',
value: state.loginModel.data!.token,
).then((value) {
showToast(
msg: state.loginModel.message!, state: ToastState.success);
});
} else {
print(state.loginModel.message);
showToast(msg: state.loginModel.message!, state: ToastState.error);
}
}
},
builder: (context, state) {
return Scaffold(
appBar: AppBar(
title: const Center(
child: Text(
'Social App',
style: TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.bold,
color: Colors.black,
),
),
),
),
body: Padding(
padding: const EdgeInsets.all(20.0),
child: SingleChildScrollView(
child: Form(
key: formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'LOGIN',
style: Theme.of(context).textTheme.headline4!.copyWith(
color: Colors.black,
fontWeight: FontWeight.bold,
),
),
const SizedBox(
height: 20.0,
),
Text(
'Login Now To Be One Of Us',
style: TextStyle(
color: Colors.grey[600],
fontSize: 20.0,
fontWeight: FontWeight.bold,
),
),
const SizedBox(
height: 30.0,
),
TextFormField(
controller: emailController,
keyboardType: TextInputType.emailAddress,
validator: (value) {
if (value!.isEmpty) {
return 'Please Enter Your Email';
}
return null;
},
onFieldSubmitted: (value) {},
decoration: InputDecoration(
label: Text(
'Email Address',
style: TextStyle(
fontSize: 15.0,
color: defaultColor,
fontWeight: FontWeight.bold,
),
),
prefixIcon: Icon(
Icons.email,
color: defaultColor,
),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
),
),
),
const SizedBox(
height: 30.0,
),
TextFormField(
controller: passwordController,
keyboardType: TextInputType.visiblePassword,
validator: (value) {
if (value!.isEmpty) {
return 'Please Enter Your Password';
}
return null;
},
obscureText: LoginCubit.get(context).isPassword,
onTap: () {
LoginCubit.get(context).changeVisibilty();
},
onFieldSubmitted: (value) {
if (formKey.currentState!.validate()) {
LoginCubit.get(context).userData(
email: emailController.text,
password: passwordController.text,
);
}
},
decoration: InputDecoration(
label: Text(
'Password',
style: TextStyle(
fontSize: 15.0,
color: defaultColor,
fontWeight: FontWeight.bold,
),
),
prefixIcon: Icon(
Icons.lock,
color: defaultColor,
),
suffixIcon: LoginCubit.get(context).suffix,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
),
),
),
const SizedBox(
height: 20.0,
),
Container(
width: double.infinity,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: defaultColor,
),
child: TextButton(
onPressed: () {
if (formKey.currentState!.validate()) {
CachceHelper.saveData(
key: 'token',
value: LoginCubit.get(context)
.loginModel!
.data!
.token!,
).then((value) {
showToast(
msg:
LoginCubit.get(context).loginModel!.message!,
state: ToastState.success,
);
});
LoginCubit.get(context).userData(
email: emailController.text,
password: passwordController.text,
);
}
},
child: const Text(
'Login',
style: TextStyle(
color: Colors.white,
fontSize: 17.0,
fontWeight: FontWeight.bold,
),
),
),
),
const SizedBox(
height: 15.0,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
'Don\'t have an account?',
style: TextStyle(
fontSize: 17.0,
fontWeight: FontWeight.bold,
color: Colors.black,
),
),
TextButton(
onPressed: () {},
child: Text(
'REGISTER',
style: TextStyle(
fontSize: 15.0,
fontWeight: FontWeight.bold,
color: defaultColor,
),
),
),
],
),
],
),
),
),
),
);
},
);
}
}
finally this is my login model
class LoginModel {
bool? status;
String? message;
LoginData? data;
LoginModel.fromJson(Map<String, dynamic> json) {
status = json['status'];
message = json['message'];
data = LoginData.fromJson(json['data']);
}
}
class LoginData {
int? id;
String? name;
String? email;
String? phone;
String? image;
String? token;
LoginData.fromJson(Map<String, dynamic> json) {
id = json['id'];
name = json['name'];
email = json['email'];
phone = json['phone'];
image = json['image'];
token = json['token'];
}
}
Also , I do not know it is the reason or not when I click restart this one shows to me after add firebase to my app but i did not use it just initialized it
Restarted application in 3,811ms.
W/DynamiteModule(14025): Local module descriptor class for com.google.android.gms.providerinstaller.dynamite not found.
I/DynamiteModule(14025): Considering local module com.google.android.gms.providerinstaller.dynamite:0 and remote module com.google.android.gms.providerinstaller.dynamite:0
W/ProviderInstaller(14025): Failed to load providerinstaller module: No acceptable module com.google.android.gms.providerinstaller.dynamite found. Local version is 0 and remote version is 0.
W/ConnectivityManager.CallbackHandler(14025): callback not found for CALLBACK_AVAILABLE message