Development Artist

[Flutter, Firebase, Issue] The argument type 'Object? Function()' can't be assigned to the parameter type 'Map<String, dynamic>'. 또는 The argument type 'DocumentReference<Object?>' can't be assigned to the parameter type 'DocumentSnapshot<Object?>'. 본문

TroubleShooting/Flutter Issue

[Flutter, Firebase, Issue] The argument type 'Object? Function()' can't be assigned to the parameter type 'Map<String, dynamic>'. 또는 The argument type 'DocumentReference<Object?>' can't be assigned to the parameter type 'DocumentSnapshot<Object?>'.

JMcunst 2022. 1. 12. 20:30
728x90
반응형

이슈

1. 플러터 인프런 강의 중, 넷플릭스 UI 만들기가 있는데, 9강에서 Movie 모델의 fromSnapshot함수를 만드는 과정이었다.

2. 다음과 같이 snapshot.data와 snapshot.reference에서 이슈가 발생.


해결

1. pubspec.yaml에서 cloud_firebase 버전을 낮게 설정한다. 다운그레이드... cloud_firestore^0.12.9+5. 또한, cloud_firestorefirebase_core에 의존성이 있어서, firebase_core^0.4.0+9. 로 맞춰 준다.  

2. 하지만, 다운그레이드가 왠 말인가...! flutter에서 해결을 해보도록 하자.

3.0. fromSnapshot 함수의 인자로 <Map<String, dynamic>> 타입으로 지정을 해준다. 그리고 fromMap에서는 <Map<String, dynamic>>? 로 인자를 수정해준다. 그리고 그 아래 title, keyword, poster, like의 map 뒤에 ?를 붙여준다. 

3.1. 해당 인자들이 무조건 온다면, null check로 title을 넣는 부분에만 map!['title']로 써도 가능하다.

3.0, 3.1


원인

1. pubspec.lock에 cloud_firebase를 찾아보면 현재 프로젝트에 설치된 cloud_firebase 패키지의 버전을 알 수 있다. 혹자의 경우, 3.1.6이였는데, 해당 버전에서는 DocumentSnapshot 클래스가 제너릭을 따르게 되면서, 타입 T의 추상 메서드를 포함하고 있다. 

abstract class DocumentSnapshot<T extends Object?> 

2. 특히 위 코드에서 Object 뒤의 ? 이것이 원인인데, Type T가 Object? 를 상속하면서 DocumentSnapshot 클래스의 메소드인 data() 함수도 마찬가지로 T?를 return 하고, flutter에서는 T?에 대한 처리가 필요하다. 

T? data();

3. 요약하자면, 기존에 DocumentSnapshot의 data로 <Map<String, dynamic>>을 채용하다가 T extends Object? 로 바꾸게 된 것이다. 쉽게 말하자면, 요런모양만 받을게~하다가 아무거나 가능해~로 바꿔서 너가 뭘로 올지 모르니 그것에 대한 처리가 필요해~라는 것이였다. (너무 비약하는 것 같긴한데...암튼 그렇다!)


참고

DocumentSnapshot : cloud_firebase version 0.13.7 / firebase_core version 0.4.0

class DocumentSnapshot {
  platform.DocumentSnapshotPlatform _delegate;
  final Firestore _firestore;

  DocumentSnapshot._(this._delegate, this._firestore);

  /// The reference that produced this snapshot
  DocumentReference get reference =>
      _firestore.document(_delegate.reference.path);

  /// Contains all the data of this snapshot
  Map<String, dynamic> get data =>
      _CodecUtility.replaceDelegatesWithValueInMap(_delegate.data, _firestore);

  /// Metadata about this snapshot concerning its source and if it has local
  /// modifications.
  SnapshotMetadata get metadata => SnapshotMetadata._(_delegate.metadata);

  /// Reads individual values from the snapshot
  dynamic operator [](String key) => data[key];

  /// Returns the ID of the snapshot's document
  String get documentID => _delegate.documentID;

  /// Returns `true` if the document exists.
  bool get exists => data != null;
}

DocumentSnapshot : cloud_firebase version 1.0.5 / firebase_core version 1.0.3

class DocumentSnapshot {
  final FirebaseFirestore _firestore;
  final DocumentSnapshotPlatform _delegate;

  DocumentSnapshot._(this._firestore, this._delegate) {
    DocumentSnapshotPlatform.verifyExtends(_delegate);
  }

  /// This document's given ID for this snapshot.
  String get id => _delegate.id;

  /// Returns the [DocumentReference] of this snapshot.
  DocumentReference get reference => _firestore.doc(_delegate.reference.path);

  /// Metadata about this [DocumentSnapshot] concerning its source and if it has local
  /// modifications.
  SnapshotMetadata get metadata => SnapshotMetadata._(_delegate.metadata);

  /// Returns `true` if the [DocumentSnapshot] exists.
  bool get exists => _delegate.exists;

  /// Contains all the data of this [DocumentSnapshot].
  Map<String, dynamic>? data() {
    return _CodecUtility.replaceDelegatesWithValueInMap(
        _delegate.data(), _firestore);
  }

  /// Gets a nested field by [String] or [FieldPath] from this [DocumentSnapshot].
  ///
  /// Data can be accessed by providing a dot-notated path or [FieldPath]
  /// which recursively finds the specified data. If no data could be found
  /// at the specified path, a [StateError] will be thrown.
  dynamic get(dynamic field) =>
      _CodecUtility.valueDecode(_delegate.get(field), _firestore);

  /// Gets a nested field by [String] or [FieldPath] from this [DocumentSnapshot].
  ///
  /// Data can be accessed by providing a dot-notated path or [FieldPath]
  /// which recursively finds the specified data. If no data could be found
  /// at the specified path, a [StateError] will be thrown.
  dynamic operator [](dynamic field) => get(field);
}

DocumentSnapshot : cloud_firebase version 3.1.6 / firebase_core version 1.11.0

@sealed
abstract class DocumentSnapshot<T extends Object?> {
  /// This document's given ID for this snapshot.
  String get id;

  /// Returns the reference of this snapshot.
  DocumentReference<T> get reference;

  /// Metadata about this document concerning its source and if it has local
  /// modifications.
  SnapshotMetadata get metadata;

  /// Returns `true` if the document exists.
  bool get exists;

  /// Contains all the data of this document snapshot.
  T? data();

  /// {@template firestore.documentsnapshot.get}
  /// Gets a nested field by [String] or [FieldPath] from this [DocumentSnapshot].
  ///
  /// Data can be accessed by providing a dot-notated path or [FieldPath]
  /// which recursively finds the specified data. If no data could be found
  /// at the specified path, a [StateError] will be thrown.
  /// {@endtemplate}
  dynamic get(Object field);

  /// {@macro firestore.documentsnapshot.get}
  dynamic operator [](Object field);
}
728x90
반응형
Comments