什么是 copyWith 以及如何在 Flutter 中使用它以及它的用例是什么?

Mil*_*del 14 forms stream dart flutter bloc

//File: email_sign_in_model.dart

class EmailSignInModel {
  EmailSignInModel({
    this.email='',
    this.formType=EmailSignInFormType.signIn,
    this.isLoading=false,
    this.password='',
    this.submitted=false,
  });

  final String email;
  final String password;
  final EmailSignInFormType formType;
  final bool isLoading;
  final bool submitted;

  EmailSignInModel copyWith({
    String email,
    String password,
    EmailSignInFormType formType,
    bool isLoading,
    bool submitted,

  }) {
    return EmailSignInModel(
    email: email ?? this.email,
    password: password?? this.password,
    formType: formType?? this.formType,
    isLoading: isLoading?? this.isLoading,
    submitted: submitted?? this.submitted

    );
  }
}



//File: email_sign_in_bloc.dart

import 'dart:async';
import 'package:timetrackerapp/app/sign_in/email_sign_in_model.dart';

class EmailSignInBloc {
 final StreamController<EmailSignInModel> _modelController = StreamController<EmailSignInModel>();
 Stream<EmailSignInModel> get modelStream => _modelController.stream;
 EmailSignInModel _model = EmailSignInModel();

 void dispose() {
   _modelController.close();
 }

void updateWith({
  String email,
  String password,
  EmailSignInFormType formType,
  bool isLoading,
  bool submitted

}) {
  //update model
  _model = _model.copyWith(
    email:email,
    password: password,
    formType: formType,
    isLoading: isLoading,
    submitted: submitted


  );
  //add updated model _tomodelController
  _modelController.add(_model);
}

}
Run Code Online (Sandbox Code Playgroud)

嗨,我是 Flutter 和 dart 的新手,并试图在 Flutter 中学习 bloc,我正在尝试使用 BLOC 并且还创建了一个模型类。我的问题是 copyWith({}) 是什么,它对 email_sign_in_model 和 email_sign_in_bloc 做了什么?代码中的 updateWith 是做什么的?谢谢!

Rit*_*ngh 19

copyWith正如前面所回答的,这是一个可以帮助改变对象的简单方法。尽管我们也可以使用简单的设置器来做到这一点。我会详细阐述答案,因为它包含bloc标签。

块和模型
在使用块模式时建议使用不可变模型,因为块模式期望用户使用支持值比较的类或模型。为了支持值比较,建议该类应该是不可变的。(高效构建需要不可变对象,您可以了解更多信息在此处了解更多信息)。

如果类是不可变的,则不能使用 setter 来更改对象的属性。相反,您需要使用 copyWith 方法使用旧值创建对象的新实例。

示例
model.dart

class Model {
  String name;
  String value;

  Model({required this.name, required this.value});
}

Run Code Online (Sandbox Code Playgroud)

这里的对象不支持值比较。因此可以使用:

void main(){
  final model = Model(name: 'my model', value: '1.9');
  model.value = '2.0';
}

Run Code Online (Sandbox Code Playgroud)

但当涉及到不可变的模型时。

@immutable
class Model {
  final String name;
  final String value;

  const Model({required this.name, required this.value});

  Model copyWith({
    String? name,
    String? value,
  }) {
    return Model(
      name: name ?? this.name,
      value: value ?? this.value,
    );
  }

  @override
  bool operator ==(Object other) {
    if (identical(this, other)) return true;
  
    return other is Model &&
      other.name == name &&
      other.value == value;
  }

  @override
  int get hashCode => name.hashCode ^ value.hashCode;
}

Run Code Online (Sandbox Code Playgroud)

现在您将无法使用 setter,因为它们是最终字段。所以你必须使用copyWith方法。

void main(){
  final model = Model(name: 'my model', value: '1.9');
  model.copyWith(value: '2.0');
}

Run Code Online (Sandbox Code Playgroud)

现在,在上面对象的 copyWith 中,您不能将值设置为可为空。为此,我们在 copyWith 方法中使用功能参数。

@immutable
class Model {
  final String name;
  final String? value;

  const Model({required this.name, required this.value});

  @override
  bool operator ==(Object other) {
    if (identical(this, other)) return true;

    return other is Model && other.name == name && other.value == value;
  }

  @override
  int get hashCode => name.hashCode ^ value.hashCode;

  Model copyWith({
    String? name,
    String? Function()? value,
  }) {
    return Model(
      name: name ?? this.name,
      value: value != null ? value() : this.value,
    );
  }
}

Run Code Online (Sandbox Code Playgroud)

现在您也可以传递空值。

void main(){
  final model = Model(name: 'my model', value: '1.9');
  model.copyWith(value: () => null);
}

Run Code Online (Sandbox Code Playgroud)

希望这能帮助您更好地使用 bloc。

  • 正是我正在寻找的东西。谢谢 (2认同)

Sri*_*lla 17

假设您有一个要更改某些属性的对象。一种方法是一次更改每个属性,诸如此类object.prop1 = x object.prop2 = y。如果要更改的属性太多,这将变得很麻烦。那么copyWith方法就派上用场了。此方法获取所有属性(需要更改)及其对应的值,并返回具有所需属性的新对象。

updateWith方法通过再次调用copyWith方法来做同样的事情,最后它将返回的对象推送到流。


小智 12

假设您有一个这样的课程:

class PostSuccess {
  final List<Post> posts;
  final bool hasReachedMax;

  const PostSuccess({this.posts, this.hasReachedMax});

functionOne(){
///Body here

} 
}
Run Code Online (Sandbox Code Playgroud)

假设您想随时随地更改类的某些属性,您可以做什么,您可以像这样声明 copyWith 方法:

PostSuccess copyWith({
    List<Post> posts,
    bool hasReachedMax,
  }) {
    return PostSuccess(
      posts: posts ?? this.posts,
      hasReachedMax: hasReachedMax ?? this.hasReachedMax,
    );
  }
  
Run Code Online (Sandbox Code Playgroud)

如您所见,在返回部分,您可以根据情况更改属性值并返回对象。