티스토리 뷰

반응형

안녕하세요. 오틸라 입니다.

 

There should be exactly one item with [DropdownButton]'s value: Instance of 'KeyValueData'. 
Either zero or 2 or more [DropdownMenuItem]s were detected with the same value

 

 

flutter에서 dropdownbutton, radiobutton, checkbox 등등 생성할때

기본코드는 text값 하나로 처리합니다.

 

 

dropdownbutton으로 예를 들면,

기본코드가

 

@override
  Widget build(BuildContext context) {
    return DropdownButton<String>(
      value: dropdownValue,
      icon: const Icon(Icons.arrow_downward),
      elevation: 16,
      style: const TextStyle(color: Colors.deepPurple),
      underline: Container(
        height: 2,
        color: Colors.deepPurpleAccent,
      ),
      onChanged: (String? value) {
        // This is called when the user selects an item.
        setState(() {
          dropdownValue = value!;
        });
      },
      items: list.map<DropdownMenuItem<String>>((String value) {
        return DropdownMenuItem<String>(
          value: value,
          child: Text(value),
        );
      }).toList(),
    );
  }

 

이런식입니다.

바인딩할때 List<String> 형태로 하고, 값 비교는 String 하나로만 합니다.

 

그런데 작업을 하다보면, key, value값으로 보여지는 텍스트와, 가져갈 값이랑 별도로 운영해야될때가 많거든요.

그래서 이걸 class로 작업하고, 클래스로 dropdownbutton을 구성하면,

 

class KeyValueData {
  final String key;
  final String value;

  KeyValueData(this.key, this.value);

  
}

이런 클래스를 하나 구현하고,

 

DropdownButton<KeyValueData>(
  value: _selectedOption_sell_type.key.isNotEmpty ? _selectedOption_sell_type : null,
  hint: Text('판매유형을 선택하세요.'), // Optional initial hint text
  onChanged: (KeyValueData? newValue) {
    setState(() {
      _selectedOption_sell_type = newValue!;
      widget.product_data.product_sell_type = newValue.key;
    });
  },
  items: sell_type_list.map((data) {
    return new DropdownMenuItem<KeyValueData>(
      value: data,
      child: new Text(
        data.value,
        style: new TextStyle(color: Colors.black),
      ),
    );
  }).toList(),
)

클래스로 key, value를 따로따로 처리합니다.

 

그런데 문제는 default값을 선택해줄때

클래스로 비교를 해주는데, 

 

 

이런 에러가 발생한다는거죠.

 

 

 

 

반응형

 

 

이 원인은

바인딩한 KeyValueData 클래스(A)와, default로 넣어준 KeyValueData(B)클래스가 값이 완전히 동일한데도 불구하고,

 

A == B  를 체크해보면, 

false로 나온다는거죠.

 

객체를 생성하면서 인스턴스값까지 비교를 하니, 다르다고 판단하는 겁니다.

 

우리는 여기서 클래스가 같고, 그중에서 key값만 같다면 그냥 같은걸로 처리해라라고 추가를 해주면 됩니다.

class KeyValueData {
  final String key;
  final String value;

  KeyValueData(this.key, this.value);

  @override
  bool operator == (Object other) {
    if(other is KeyValueData && other.key == key)
      return true;
    else
      return false;
  }
}

 

operator를 오버라이드 하고,

아까 얘기한, KeyValueData라는 클래스가 같고, 그 클래스값중에 key가 같으면 return true (같은거다)

라고 조건을 재정의 해주면 됩니다.

 

좀더 간단하게는

class KeyValueData {
  final String key;
  final String value;

  KeyValueData(this.key, this.value);

  @override
  bool operator == (Object other) => other is KeyValueData && other.key == key;
}

 

요렇게 적어도 됩니다.

 

그러면, 이제 클래스끼리 A == B를 비교할때 안에 들어있는 key값이 같으면 통과 됩니다.

 

 

 

 

이상 오틸라였습니다.

건강하세요~

반응형
댓글