Mobile/Flutter

[Flutter] 무한 스크롤 구현 해보기 + 검색

펭귄알 2024. 8. 7. 13:17

이번 글에서는 무한 스크롤에 대해 소개해보겠습니다.

 

우선 무한 스크롤은 다양한 앱에 적용되어있습니다. 이것은 댓글이나 게시글 등 페이징 처리가 된 UI에서 유용하게 사용됩니다. 

 

페이지를 클릭해서 사용하는 방법도 좋지만 스크롤만 내리면 지연 로딩을 통해 데이터를 보여주는 방법이 자주 사용되고 있으므로 여러분들도 개발을 햘 때 유용하게 사용할 것이라고 생각됩니다.

무한 스크롤을 직접 구현해도 됩니다. 하지만 신경써줘야 할 부분이 몇 가지 있죠.

- 스크롤 위치가 최하단인지 판별,

- 마지막 페이지 인지 확인

- 현재 페이지 번호 

- 로딩 상태 관리

- 에러 처리

 

위 내용 말고도 요구사항에 따라 더 많은 고려사항이 있을수도 있습니다.

 

저는 직접 구현 해서 사용하다가, 인기있는 무한 스크롤 라이브러리를 찾아서 소개할려고합니다.

Infinite Scroll Pagination (링크)

사용자가 화면을 아래로 스크롤할 때 작은 청크의 항목을 느리게 로드하여 표시하는 데 도움이 되는, 편견 없고 확장 가능하며 높은 사용자 정의가 가능한 패키지입니다. 무한 스크롤 페이징, 무한 스크롤 페이징, 자동 페이징, 지연 로딩 페이징, 점진적 로딩 페이징 등으로 불립니다.

 

특징 

  • 아키텍처 독립적 : setState 에서 BLoC 까지 모든 상태 관리 접근 방식과 호환됩니다 .
  • 레이아웃에 구애받지 않음 : GridView , SliverGrid , ListView  SliverList 에 해당하는 기본 위젯 (생성자 포함) .separated 등을 사용해 사용자 지정 레이아웃을 쉽게 만들 수 있습니다 .
  • API에 구애받지 않음 : Infinite Scroll Pagination은 사용자가 API 호출을 완벽하게 제어할 수 있게 해주므로 모든 페이지네이션 전략 에 적합합니다 .
  • 사용자 정의 가능 : 모든 것을 변경할 수 있습니다 . 진행 상황, 오류 및 빈 목록 표시기를 직접 제공하세요. 변경하기 너무 귀찮으신가요? 기본값이 당신을 보호할 것입니다.
  • 확장성 : 당겨서 새로 고침 , 검색, 필터링 및 정렬 기능을 원활하게 통합합니다 .
  • 상태 변경 수신 : 진행률 및 오류 표시기와 같은 현재 상태를 알려주는 위젯을 표시하는 것 외에도 리스너를 사용하여 대화 상자/스낵바/토스트를 표시하거나 다른 작업을 실행할 수 있습니다.

API Diagram

공통

  • PagingController
    • 이 컨트롤러는 페이징 상태를 가져오고 필요할 때 항목을 요청하는 데 사용됩니다.
  • PagedChildBuilderDelegate
    • 이 델리게이트는 각 UI 조각(예: 리스트 항목, 진행 상태, 오류 표시기 등)을 위한 빌더를 제공합니다.

위젯 (Widgets)

모든 위젯은 두 가지 공통 속성을 가지고 있습니다:

  1. pagingController: PagingController의 인스턴스입니다.
  2. builderDelegate: PagedChildBuilderDelegate의 인스턴스입니다.

리스트 위젯 (List Widgets)

  • PagedListView: ListView에 해당하며 모든 일반적인 ListView 속성을 포함합니다.
  • PagedSliverList: SliverList에 해당하며 모든 일반적인 SliverList 속성을 포함합니다.

그리드 위젯 (Grid Widgets)

  • PagedGridView: GridView에 해당하며 모든 일반적인 GridView 속성을 포함합니다.
  • PagedMasonryGridView: MasonryGridView에 해당하며 모든 일반적인 MasonryGridView 속성을 포함합니다.
  • PagedSliverGrid: SliverGrid에 해당하며 모든 일반적인 SliverGrid 속성을 포함합니다.

기타 위젯 (Other Widgets)

  • PagedPageView: PageView에 해당하며 모든 일반적인 PageView 속성을 포함합니다.

PagedLayoutBuilder

  • 모든 상위 레벨 위젯의 골격 역할을 합니다.
  • 위의 위젯들이 레이아웃에 맞지 않을 경우 직접 사용할 수 있습니다.

사용법

1. PagingController 생성

pagingController를 생성하고 타입을 명시해줍니다.

생성한 controller에 listener를 추가하고 페이지를 호출할 때마다 pageKey를 통해 현재 페이지를 파라미터로 전달해줍니다.

2. 데이터 요청

여기서는 listener에서 받은 pageKey를 통해 API요청을 처리합니다.

해당 코드에서는 예시 데이터로 처리하였지만, 실제 API 요청시에는 현재 페이지가 마지막페이지 인지 판별하여 controller에 데이터를 주입합니다. 또한 try-catch구문으로 error를 주입하면 error 발생시에 UI 표현도 가능합니다.

3. UI

여기서는 PagedListView 위젯을 통해 controller에 있는 값들을 표현합니다.

 

API Diagram에서 소개한 pagingController와 builderDelegate는 필수 요소이며, 나머지 요소는 필요에 따라 작성하여 ListView를 보다 커스텀하게 작업가능합니다.

 

+ Seperated

각 항목해 대해 구분선이 필요하다면 Seperated를 이용해 표현도 가능합니다.

 

PagedChildBuiderDelegate

PagedChildBuilderDelegate 내에 속성을 보시면 각 속성에 맞는 모든 요소들을 제어할 수 있습니다.

 

  • itemBuilder: 아이템을 빌드하는 데 필요한 필수 빌더 함수입니다.
  • firstPageErrorIndicatorBuilder: 첫 페이지 로딩 시 오류가 발생할 때 사용할 오류 표시기 빌더입니다.
  • newPageErrorIndicatorBuilder: 새로운 페이지를 로딩하는 도중 오류가 발생할 때 사용할 오류 표시기 빌더입니다.
  • firstPageProgressIndicatorBuilder: 첫 페이지 로딩 중에 사용할 진행 상태 표시기 빌더입니다.
  • newPageProgressIndicatorBuilder: 새로운 페이지를 로딩하는 도중에 사용할 진행 상태 표시기 빌더입니다.
  • noItemsFoundIndicatorBuilder: 항목을 찾을 수 없을 때 사용할 표시기 빌더입니다.
  • noMoreItemsIndicatorBuilder: 더 이상 로드할 항목이 없을 때 사용할 표시기 빌더입니다.
  • animateTransitions: 전환 시 애니메이션을 사용할지 여부를 지정합니다.
  • transitionDuration: 전환 애니메이션의 지속 시간을 지정합니다.

검색 및 필터링

검색 및 필터링을 진행할 경우에는 다른 방법으로 시도해보았습니다. 검색 해도 자료가 많지 않아서 제가 작성한 코드를 설명드리겠습니다.(Riverpod 사용)

fetchData를 통해 데이터를 가져옵니다.

현재 데이터를 패치할 때 사용되는 함수입니다.

검색 파라미터에 있는 값들이 있는지 없는지 확인 후 검색을 진행합니다.

1. pagingController의 firstPageKey를 0으로 초기화합니다

2. state의 pagingController에 새로운 상태를 추가합니다.

3. pagingController에 페이지가 0으로 변경되었다는것을 알립니다.

 

기본적인 라이브러리 및 검색/필터링 하는 방법까지 알아보았는데 도움이되셨으면 좋겠습니다. 오늘도 빡코딩!