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

问题描述 投票:0回答:3
//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);
}

}

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

forms flutter dart stream bloc
3个回答
43
投票

假设您有一个对象想要更改其中的某些属性。一种方法是一次更改每个属性,例如

object.prop1 = x
object.prop2 = y
等等。如果您要更改的属性较多,这将变得很麻烦。那么
copyWith
方法就派上用场了。此方法获取所有属性(需要更改)及其相应的值,并返回具有您所需属性的新对象。

updateWith
方法通过再次调用
copyWith
方法执行相同的操作,最后将返回的对象推送到流中。


31
投票

假设你有一个类似的课程:

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

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

functionOne(){
///Body here

} 
}

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

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

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


19
投票
之前回答的

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

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

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

示例 模型.dart

class Model { String name; String value; Model({required this.name, required this.value}); }
这里的对象不支持值比较。因此可以使用:

void main(){ final model = Model(name: 'my model', value: '1.9'); model.value = '2.0'; }
但是当涉及到不可变的模型时。

@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; }
现在您将无法使用 setter,因为它们是最终字段。所以你必须使用copyWith方法。

void main(){ final model = Model(name: 'my model', value: '1.9'); model.copyWith(value: '2.0'); }
现在在上面对象的 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, ); } }
现在您也可以传递空值。

void main(){ final model = Model(name: 'my model', value: '1.9'); model.copyWith(value: () => null); }
希望这能帮助您更好地使用 bloc。

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