dart 空安全性错误:无条件访问Flutter Riverpod中的“状态”属性

ruyhziif  于 2023-06-19  发布在  Flutter
关注(0)|答案(1)|浏览(125)

我在尝试访问'state'属性时遇到Flutter Riverpod代码中的空安全错误。错误消息说:
“属性'state'不能无条件访问,因为接收者可以是'null'。尝试设置访问条件(使用'?.')或向目标('!').”
主要目标是使用Riverpod作为状态管理解决方案来更新图像,确保其在Web浏览器和移动的设备上无缝工作。
下面的代码片段演示了这个问题:

import 'dart:io';
import 'dart:typed_data';
import 'package:provider/provider.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

final pickedImageProvider = StateProvider<File?>((ref) => null);
final webImageProvider = StateProvider<Uint8List>((ref) => Uint8List(8));
final tapOffsetProvider = StateProvider<Offset?>((ref) => null);

class ProfileAppBar extends ConsumerWidget {
  const ProfileAppBar({Key? key}) : super(key: key);

  Future<void> _pickImage(BuildContext context) async {
    if (!kIsWeb) {
      final ImagePicker picker = ImagePicker();
      XFile? image = await picker.pickImage(source: ImageSource.gallery);
      if (image != null) {
        var selected = File(image.path);
        context.read(pickedImageProvider).state = selected;
      } else {
        print('No image has been picked ');
      }
    } else if (kIsWeb) {
      final ImagePicker picker = ImagePicker();
      XFile? image = await picker.pickImage(source: ImageSource.gallery);
      if (image != null) {
        var f = await image.readAsBytes();
        context.read(webImageProvider).state = f;
        context.read(pickedImageProvider).state = File('a');
      } else {
        print('No image has been picked ');
      }
    } else {
      print('Something went wrong');
    }
  }

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    return SafeArea(
      child: Scaffold(
        appBar: AppBar(
          ...   Row(
                mainAxisAlignment: MainAxisAlignment.spaceAround,
                children: [
                  Tooltip(
                    message: 'Settings',
                    child: Semantics(
                      label: 'Pomodoro timer settings',
                      enabled: true,
                      readOnly: true,
                      child: IconButton(
                        icon: const Icon(
                          Icons.settings_outlined,
                          color: Color(0xff3B3B3B),
                          size: 24,
                          semanticLabel: 'Pomodoro timer Settings',
                        ),
                        onPressed: () {
                          Navigator.push(
                            context,
                            MaterialPageRoute(
                              builder: (context) => const Scaffold(),
                            ),
                          );
                        },
                      ),
                    ),
                  ),
                  GestureDetector(
                    behavior: HitTestBehavior.translucent,
                    onTapDown: (details) {
                      ref.read(tapOffsetProvider).state =
                          details.globalPosition;
                    },
                    child: IconButton(
                      onPressed: () {
                        final tapOffset = ref.watch(tapOffsetProvider).state;
                        if (tapOffset != null) {
                          showMenu(
                            position: RelativeRect.fromLTRB(
                              tapOffset!.dx - 150,
                              64,
                              tapOffset.dx ?? 0,
                              0,
                            ),
                            constraints: const BoxConstraints(
                              maxWidth: 600,
                            ),...
        ),
      ),
    );
  }
}

当我尝试设置context.read().state的状态时,错误特别发生在_pickImage方法中。我应该如何调整我的代码来使对'state'属性的访问有条件,或者我应该如何正确地添加空检查来避免这个错误?

nue99wik

nue99wik1#

你的代码应该可以正常工作!我只看到按钮有一个问题:

IconButton(
onPressed: () {
  final tapOffset = ref.read(tapOffsetProvider); // `state` don't required
  if (tapOffset != null) {...}

在回调中,必须使用ref.read
若要使用您的提供程序,只需添加!(如果您确定值不是null)或使用?

final pickedImageProvider = StateProvider<File?>((ref) => null);

{
  File? pickedImage = ref.read(pickedImageProvider);
  File pickedImageNotNull = ref.read(pickedImageProvider)!;

  String? pickedImagePath = ref.read(pickedImageProvider)?.path;
  String pickedImagePathNotNull = ref.read(pickedImageProvider)!.path;
}

但实际上你的问题是你忘记使用.notifier,并且没有正确地尝试访问状态:

context.read(pickedImageProvider.notifier).state = selected;
context.read(webImageProvider.notifier).state = f;
context.read(pickedImageProvider.notifier).state = File('a');

// Or do it this way:
context.read(pickedImageProvider.notifier).update((_) => selected);
context.read(webImageProvider.notifier).update((_) => f);
context.read(pickedImageProvider.notifier).update((_) => File('a'));

相关问题