ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • ScrollablePositionedList.builder를 사용할 때 성능을 최적화하려면
    카테고리 없음 2024. 11. 28. 23:04

    ScrollablePositionedList.builder를 사용할 때 성능을 최적화하려면 다음과 같은 방안을 고려할 수 있습니다. 이 위젯은 특히 긴 리스트를 처리할 때 최적화를 통해 렌더링 비용과 메모리 사용량을 줄이는 것이 중요합니다.


    1. itemCount와 데이터 제공

    itemCount를 명시하여 불필요한 데이터 계산을 피하세요.

    ScrollablePositionedList.builder(
      itemCount: messages.length, // 전체 메시지 개수 제공
      itemBuilder: (context, index) {
        final message = messages[index];
        return MessageWidget(message: message);
      },
      reverse: true, // 가장 최근 메시지가 위로 오도록
      initialScrollIndex: 0, // 기본 위치를 마지막 메시지로
    );
    
    • 효과: itemCount가 지정되면 Flutter는 빌드할 범위를 더 정확히 예측하고 최적화된 렌더링을 수행합니다.

    2. addAutomaticKeepAlives, addRepaintBoundaries 설정

    리스트 빌딩 옵션으로 성능 튜닝을 진행할 수 있습니다.

    ScrollablePositionedList.builder(
      itemCount: messages.length,
      itemBuilder: (context, index) {
        return MessageWidget(message: messages[index]);
      },
      reverse: true,
      addAutomaticKeepAlives: false, // 불필요한 상태 유지 비활성화
      addRepaintBoundaries: false, // Repaint 영역 최소화
    );
    
    • addAutomaticKeepAlives: 상태 유지가 불필요한 경우 false로 설정.
    • addRepaintBoundaries: Repaint 범위를 최소화해 성능 개선.

    3. reverse 최적화

    reverse: true는 새로 추가된 메시지가 리스트 상단에 배치되도록 합니다. 그러나 성능에 문제가 발생하면 데이터 리스트를 직접 뒤집고 reverse: false를 사용해보세요.

    ScrollablePositionedList.builder(
      itemCount: messages.length,
      itemBuilder: (context, index) {
        final message = messages[messages.length - 1 - index]; // 리스트를 역순으로 매핑
        return MessageWidget(message: message);
      },
      reverse: false, // 데이터 리스트를 직접 뒤집었으므로 reverse 비활성화
    );
    
    • 효과: reverse가 내부적으로 처리하는 연산을 줄이고 더 나은 성능을 얻을 수 있습니다.

    4. Lazy Loading 구현

    ScrollablePositionedList를 사용할 때 무한 스크롤을 구현하면 초기에 로드되는 데이터 양을 줄일 수 있습니다.

    final int initialLoadCount = 50; // 초기 로드 메시지 수
    List<ChatMessage> displayedMessages = messages.take(initialLoadCount).toList();
    
    // 더 가져오기 메서드
    void loadMoreMessages() {
      setState(() {
        final additionalCount = 50; // 한 번에 추가 로드할 메시지 수
        displayedMessages = messages.take(displayedMessages.length + additionalCount).toList();
      });
    }
    
    // 스크롤 끝 감지
    ScrollablePositionedList.builder(
      itemCount: displayedMessages.length,
      itemBuilder: (context, index) {
        if (index == displayedMessages.length - 1 && displayedMessages.length < messages.length) {
          loadMoreMessages(); // 스크롤 끝에서 추가 로드
        }
        return MessageWidget(message: displayedMessages[index]);
      },
      reverse: true,
    );
    
    • 효과: 초기 로딩 데이터를 제한하고, 스크롤 이벤트에 따라 데이터를 점진적으로 로드.

    5. Indexed Cache 사용

    ScrollablePositionedList는 자동으로 IndexedScrollController를 활용하지만, 추가로 캐싱하여 성능을 향상할 수 있습니다.

    final ItemScrollController itemScrollController = ItemScrollController();
    
    ScrollablePositionedList.builder(
      itemCount: messages.length,
      itemBuilder: (context, index) {
        return CachedWidget(index: index, child: MessageWidget(message: messages[index]));
      },
      itemScrollController: itemScrollController,
      reverse: true,
    );
    

    CachedWidget처럼 특정 아이템을 캐싱하는 위젯을 사용해 이전에 빌드된 위젯을 재활용하면 성능을 높일 수 있습니다.


    6. Flutter DevTools로 성능 분석

    Flutter DevTools에서 ScrollablePositionedList의 렌더링 성능을 분석하세요.

    • Jank 탐지: 프레임 드롭 여부 확인.
    • Rebuild Count: 불필요한 빌드가 발생하는 경우 최적화.

    요약

    1. itemCount와 데이터 리스트 최적화.
    2. addAutomaticKeepAlives와 addRepaintBoundaries 설정.
    3. 데이터 리스트를 뒤집어 reverse 로직 간소화.
    4. Lazy Loading 구현으로 초기 데이터 로드 제한.
    5. Indexed Cache를 활용한 위젯 재사용.
    6. DevTools로 성능 병목 식별.

    위의 방법을 조합하여 성능을 최적화하면 원활한 스크롤 경험을 제공할 수 있습니다! 🚀

Designed by Tistory.