如何将 Future 方法从有状态小部件移动到它们自己的 class Flutter

How to move Future methods from Stateful widget to their own class Flutter

我有几个 Future 方法包含在有状态小部件中。相同的方法出现在应用程序的不同部分。我想将这些方法添加到一个 Class 而不是在应用程序中重写四次,但我一直无法弄清楚,因为有几个方法调用 setState 来更新 UI。当用户从他们的图库中选择图像、选择拍照、将所选图像上传到数据库以在应用程序中显示、压缩图像等时调用这些方法。

class ExampleClass extends StatefulWidget {
  const ExampleClass({Key? key}) : super(key: key);

  @override
  State<ExampleClass> createState() => _ExampleClassState();
}

class _ExampleClassState extends State<ExampleClass> {
  File? file;

  Future<void> _captureImageWithCamera() async {
    Get.back();
    XFile? pickedFile = await ImagePicker().pickImage(
      source: ImageSource.camera,
    );
    setState(() {
      file = File(pickedFile!.path);
    });
  }

  @override
  Widget build(BuildContext context) {
    return Container();
  }
}

我只包含其中一种方法 (captureImageWithCamera),假设针对其中一种方法的建议解决方案可以应用于所有方法。如果我需要提供更多代码,我会很乐意这样做。任何帮助将不胜感激。

您可以从提取的方法中 return pickedFile,然后每个使用结果的 class 都可以使用 returned 值调用 setState 本身。

class ImageCapturer {
  Future<XFile?> captureImageWithCamera() async {
    Get.back();
    XFile? pickedFile = await ImagePicker().pickImage(
      source: ImageSource.camera,
    );
    
    return pickedFile;
  }
}

class ExampleClass extends StatefulWidget {
  const ExampleClass({Key? key}) : super(key: key);

  @override
  State<ExampleClass> createState() => _ExampleClassState();
}

class _ExampleClassState extends State<ExampleClass> {
  File? file;

  Future<void> _captureImageWithCamera() async {
    final file = await ImageCapturer().captureImageWithCamera();

    setState(() {
      this.file = File(file!.path);;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Container();
  }
}

您可以使用回调参数将代码抽象为一个函数,如下所示:

class OtherExampleClass {
  Future<void> captureImageWithCamera(
        void Function(XFile? pickedFile) callback,
    ) async {
    Get.back();
    XFile? pickedFile = await ImagePicker().pickImage(
      source: ImageSource.camera,
    );
    
    callback(pickedFile);
  }
}

class ExampleClass extends StatefulWidget {
  const ExampleClass({Key? key}) : super(key: key);

  @override
  State<ExampleClass> createState() => _ExampleClassState();
}

class _ExampleClassState extends State<ExampleClass> {
  File? file;

  Future<void> _captureImageWithCamera() async {
    await OtherExampleClass().captureImageWithCamera((XFile? pickedFile) {
            setState(() {
                file = File(pickedFile!.path);
            });
        }
    );
  }

  @override
  Widget build(BuildContext context) {
    return Container();
  }
}

当您将第三方库用于应用程序外部的某些内容时,例如选择照片、下载一些数据、进行 http 调用。 考虑为这些东西创建服务 class,服务 class 基本上是这样的: a class 具有单一职责,像这样 class 应该只做一件事。 在您的情况下,您应该创建 ImagePickerService class 工作是选择一个图像,return 仅此而已,您不应该在其中调用任何 flutter 框架 喜欢 setState 因为更新 UI.

不是他的工作
class ImagePickerService {
  //make this class singleton so you do not make a new instance every time you want it.
  static final ImagePickerService _instance = ImagePickerService._(); 
  ImagePickerService._();
  factory ImagePickerService() => _instance;

  Future<XFile?> pickImage(ImageSource imageSource) async {
    return await ImagePicker().pickImage(
      source: imageSource,
    );
  }
}

所以现在当你想要选择一个图像时,你只需要像这样调用这个服务。

onTap: () async {
    final file = await ImagePickerService().pickImage(ImageSource.camera);
    setState(() {
      // you got the file boss do anything you want
    });
  }

现在,当您创建新页面时,您只需创建页面并在其中定义一些服务。