我开发一个商店应用程序来学习。 当我尝试从 API 获取数据时,我总是遇到这个问题:
对空值使用空检查运算符
无论我做什么,我都会遇到这个错误。
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,
),
),
);
}
}
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');
});
}
}
}
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);
}
}
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!);
}
}
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'];
}
}
调试后发现错误发生在Cubit File中的getHomeData方法处, 但找不到任何解决方案。
我猜错误来自这一行:
printFullText(homeModel!.data!.banners[0].image);
那里的那些感叹号(称为“非空断言运算符”)意味着您期望
homeModel
不为空并且 homeModel.data
不为空。这个期望太高了,因为这些值来自解析 HTTP 响应。
可能的解决方案:
homeModel
和homeModel.data
,如果为空则正确反应。在这两种情况下,请删除
!
运算符。