Flutter null 检查运算符用于 null 值?

问题描述 投票:0回答:1

我开发一个商店应用程序来学习。 当我尝试从 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');
          });
        }
  }
}

Dio 帮助文件:

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方法处, 但找不到任何解决方案。

android flutter dart mobile
1个回答
0
投票

我猜错误来自这一行:

printFullText(homeModel!.data!.banners[0].image);

那里的那些感叹号(称为“非空断言运算符”)意味着您期望

homeModel
不为空并且
homeModel.data
不为空。这个期望太高了,因为这些值来自解析 HTTP 响应。

可能的解决方案:

  1. 使用前检查
    homeModel
    homeModel.data
    ,如果为空则正确反应。
  2. 将使用这些值执行的所有操作都放在 try-catch 中,并在引发 NoSuchMethodError 时做出正确反应。

在这两种情况下,请删除

!
运算符。

© www.soinside.com 2019 - 2024. All rights reserved.