TextEditingController를 활용하는 과정에서 2가지 문제가 생겼다.
의도)
검색창 안에 값이 없는 상태에서 전체 데이터가 보여야 하고, 검색어를 입력하면 검색어에 해당하는 데이터만 보여야 한다.
문제 발생)
- 앱을 처음 실행했을 때 전체 데이터가 보이면 좋겠는데, 첫 화면에서 아무것도 보이지 않았다. 데이터가 잘 들어오는지 확인했는데도 말이다.
- 그런데 검색어가 없는 상태에서 돋보기를 클릭하고 나면 또 전체 데이터가 보인다.
문제 원인)
- 아래 코드를 보면 searchItem 함수가 initState 안에 있긴 하지만, getData 보다 먼저 실행되고 있다.
- getData는 Future이기 때문에 늦게 실행이 된다. getData가 완료되야 result 리스트가 채워지고, searchItem은 그 result를 활용해서 필터링을 한다. 따라서 getData가 실행된 후 searchItem이 실행되도록 해야 한다.
class MainPage extends StatefulWidget {
const MainPage({super.key});
@override
State<MainPage> createState() => _MainPageState();
}
class _MainPageState extends State<MainPage> {
List result = [];
List filterdResult = [];
final TextEditingController controller = TextEditingController();
@override
void dispose() {
controller.dispose();
super.dispose();
}
@override
void initState() {
searchItem(""); // 오류 원인
getData();
super.initState();
}
Dio dio = Dio();
Future getData() async {
final response = await dio.get(
'http://openapi.seoul.go.kr:8088/sample/json/lostArticleInfo/1/5/');
setState(() {
result = response.data['lostArticleInfo']['row'];
});
}
void searchItem(String query) {
setState(() {
filterdResult = result
.where((item) => item['GET_NAME'].toString().contains(query))
.toList();
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('분실물 찾기'),
),
... 생략 ...
의도)
검색창에 단어를 입력하고 엔터를 쳤을 때 검색이 되어야 한다.
문제발생)
하지만 이상하게도 검색창에 입력을 하는 중에 실시간으로 검색이 이루어졌다.
문제원인)
- 원인은 바로 onChanged를 썼기 때문이다.
- 검색창에 입력(or삭제)가 있을 때마다 실행되기 때문에 엔터와 같은 동작이 있는 후에 검색결과가 나오려면 onPressed를 활용해야 했다.
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('분실물 찾기'),
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
TextField(
controller: controller,
onChanged: (value) { // 오류 원인
searchItem(controller.text);
},
decoration: InputDecoration(
labelText: '분실물을 입력하세요',
border: const OutlineInputBorder(),
),
),
),