I work on a shop app for learning.
And when I try to get data from the API, I always have this problem:
Null check operator used on a null value
And no matter what I do I keep having this error.
Here are my code blocks:
Main File:
void main() async
{
//this line of code ensures that all the data are set and get before running the app
WidgetsFlutterBinding.ensureInitialized();
Bloc.observer = MyBlocObserver();
DioHelper.init();
await CacheHelper.init();
Widget? widget;
bool? isDarkTheme = CacheHelper.getData(key: 'isDark') ?? false;
bool? onBoarding = CacheHelper.getData(key: 'onBoarding') ?? false;
token = CacheHelper.getData(key: 'token')??'';
print(token);
if(onBoarding != null && onBoarding)
{
widget = token.isNotEmpty? ShopLayout() : ShopLoginScreen();
}
else {
widget = OnBoardingScreen();
}
runApp(MyApp(isDarkTheme: isDarkTheme ,startWidget: widget));
}
class MyApp extends StatelessWidget
{
final bool? isDarkTheme;
final Widget? startWidget;
MyApp({@required this.isDarkTheme, @required this.startWidget});
@override
Widget build(BuildContext context) {
return MultiBlocProvider(
providers:
[
BlocProvider(create: (BuildContext context) => ShopCubit()..changeAppMode(isDarkFromPreferences: isDarkTheme)),
BlocProvider(create: (BuildContext context) => ShopCubit()..getHomeData()),
BlocProvider(create: (BuildContext context) => WhatsappCubit()),
],
child: BlocConsumer<ShopCubit, ShopStates>(
listener: (context, state){},
builder: (context, state) => MaterialApp
(
theme: lightTheme,
darkTheme: darkTheme,
themeMode: ThemeMode.light,//isDarkTheme!? ThemeMode.dark: ThemeMode.dark,
debugShowCheckedModeBanner: false,
home: startWidget,
),
),
);
}
}
Cubit File:
class ShopCubit extends Cubit<ShopStates>
{
ShopCubit() : super(ShopInitialState());
static ShopCubit get(context) => BlocProvider.of(context);
int currentIndex = 0;
bool isDark = true;
ThemeMode? appTheme;
List<Widget> screens =
[
ProductsScreen(),
CategoriesScreen(),
FavouritesScreen(),
SettingsScreen(),
];
void changeBottomSheetIndex(int index)
{
currentIndex = index;
emit(ShopChangeBottomNavCurrentIndexState());
}
HomeModel? homeModel;
void getHomeData()
{
emit(ShopLoadingHomeDataState());
DioHelper.getData(path: HOME, token: token).then((value) {
if (value.data != null) {
homeModel = HomeModel.fromJson(value.data);
print('Data fetched successfully');
printFullText(homeModel!.data!.banners[0].image);
emit(ShopSuccessHomeDataState());
}
else
{
emit(ShopErrorHomeDataState('Response data is null'));
}
}).catchError((error) {
emit(ShopErrorHomeDataState(error.toString()));
print('Error fetching data: ${error.toString()}');
});
}
void changeAppMode({bool? isDarkFromPreferences})
{
if(isDarkFromPreferences != null)
{
isDark = isDarkFromPreferences;
emit(ShopChangeAppModeState());
}
else
{
isDark = !isDark;
}
if(isDark)
{
appTheme = ThemeMode.dark;
CacheHelper.saveData(key: 'isDark', value: isDark).then((value)
{
emit(ShopChangeAppModeState());
}).catchError((error)
{
print('An error occurred while trying to set a new value as a shared preference');
});
} else
{
appTheme = ThemeMode.light;
CacheHelper.saveData(key: 'isDark', value: isDark).then((value)
{
emit(ShopChangeAppModeState());
}).catchError((error)
{
print('An error occurred while trying to set a new value as a shared preference');
});
}
}
}
Dio Helper File:
class DioHelper {
static Dio? dio;
static void init() {
dio = Dio(
BaseOptions(
baseUrl: 'https://student.valuxapps.com/api/',
receiveDataWhenStatusError: true,
),
);
}
static Future<Response> getData({
@required String? path,
Map<String, dynamic>? query,
String lang = 'en',
String? token,
})
async
{
dio!.options.headers = {
'Content-Type':'application/json',
'lang':lang,
'Authorization':token??'',
};
return await dio!.get(path!, queryParameters: query!);
}
static Future<Response> postData({
@required String? url,
Map<String, dynamic>? query,
@required Map<String, dynamic>? data,
String lang = 'en',
String? token,
}) async
{
dio!.options.headers = {
'Content-Type':'application/json',
'lang':lang,
'Authorization':token??'',
};
return dio!.post(url!, queryParameters: query, data: data);
}
}
Cache Helper File:
class CacheHelper
{
static SharedPreferences? sharedPreferences;
static Future<void> init() async
{
sharedPreferences = await SharedPreferences.getInstance();
}
static dynamic getData({@required String? key})
{
if(sharedPreferences == null) {
return 'error this value is null';
}
return sharedPreferences!.get(key!);
}
static Future<bool> saveData({
@required String? key,
@required dynamic value,
}) async
{
if(value is String) return await sharedPreferences!.setString(key!, value);
if(value is int) return await sharedPreferences!.setInt(key!, value);
if(value is bool) return await sharedPreferences!.setBool(key!, value);
return await sharedPreferences!.setDouble(key!, value);
}
static Future<bool> removeData({@required String? key}) async
{
return await sharedPreferences!.remove(key!);
}
}
Data Receive File:
class HomeModel
{
bool? status;
HomeDataModel? data;
HomeModel.fromJson(Map<String, dynamic> json)
{
status = json['status'];
data = HomeDataModel.fromJson(json['data']);
}
}
class HomeDataModel
{
List<BannerModel> banners = [];
List<ProductModel> products = [];
HomeDataModel.fromJson(Map<String, dynamic> json)
{
json['banners'].forEach((element)
{
banners.add(element);
});
json['products'].forEach((element)
{
products.add(element);
});
}
}
class BannerModel
{
int? id;
String? image;
BannerModel.fromJson(Map<String, dynamic> json)
{
id = json['id'];
image = json['image'];
}
}
class ProductModel
{
int? id;
dynamic price;
dynamic oldPrice;
dynamic discount;
String? image;
String? name;
bool inFavourites = false;
bool inCart = false;
ProductModel.fromJson(Map<String, dynamic> json)
{
id = json['id'];
price = json['price'];
oldPrice = json['old_price'];
discount = json['discount'];
image = json['image'];
name = json['name'];
inFavourites = json['in_favourites'];
inCart = json['in_cart'];
}
}
note
After making a debug I found that the error occurs at the getHomeData method in the Cubit File,
but couldn’t find any Solutions.
Omar Nasr is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
1
I guess the error comes from this line:
printFullText(homeModel!.data!.banners[0].image);
Those exclamation marks there (called “non-null assertion operators”) mean that you expect homeModel
not to be null and homeModel.data
not to be null. That’s too much to expect, because these values come from parsing an HTTP response.
Possible solutions:
- Check
homeModel
andhomeModel.data
before using them, and if they are null react properly. - Place everything you do with those values in a try-catch and react properly when the NoSuchMethodError is raised.
In both cases, remove the !
operators.