TextEditingController (feat. 비동기)

Angela Jeong·2024년 1월 10일
0

Flutter Troubleshooting

목록 보기
6/19
post-thumbnail

TextEditingController를 활용하는 과정에서 2가지 문제가 생겼다.

문제 1. 앱이 처음 실행될 때 데이터가 보이지 않는다.

의도)

검색창 안에 값이 없는 상태에서 전체 데이터가 보여야 하고, 검색어를 입력하면 검색어에 해당하는 데이터만 보여야 한다.

문제 발생)

  • 앱을 처음 실행했을 때 전체 데이터가 보이면 좋겠는데, 첫 화면에서 아무것도 보이지 않았다. 데이터가 잘 들어오는지 확인했는데도 말이다.
  • 그런데 검색어가 없는 상태에서 돋보기를 클릭하고 나면 또 전체 데이터가 보인다.

문제 원인)

  • 아래 코드를 보면 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('분실물 찾기'),
      ),
      
      ... 생략 ...
  


문제 2. 검색어를 입력하는 도중에 실시간으로 필터링이 된다.

의도)

검색창에 단어를 입력하고 엔터를 쳤을 때 검색이 되어야 한다.

문제발생)

하지만 이상하게도 검색창에 입력을 하는 중에 실시간으로 검색이 이루어졌다.

문제원인)

  • 원인은 바로 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(),
                ),
              ),
            ),


전체코드: [AngieEJJ의 github](https://github.com/AngieEJJ/lost-and-found-api/tree/first_step/lib)

0개의 댓글