인프런 커뮤니티 질문&답변

GO님의 프로필 이미지
GO

작성한 질문수

[코드팩토리] [중급] Flutter 진짜 실전! 상태관리, 캐시관리, Code Generation, GoRouter, 인증로직 등 중수가 되기 위한 필수 스킬들!

RefreshIndicator 작업하기

주문페이지 리프레쉬 인디케이터 문제

작성

·

404

0

안녕하세요 선생님

해당 강의내용에서 당겨서 새로고침하는 리프레쉬 인디케이터를 사용하면 상단에 로딩바가 하나 도는데

다시 화면이 리프레쉬되면서 화면 중앙에 로딩바가 도는 것이 2중 로딩으로 보여지는 것 같아서

pagination_list_view.dart 파일내

RefreshIndicator(
          onRefresh: () async {
            ref.read(widget.provider.notifier).paginate(forceRefetch: true);
          },

위 코드의 forceRefetch: true 를 삭제하는게 더 낫겠다는 판단에

RefreshIndicator(
          onRefresh: () async {
            ref.read(widget.provider.notifier).paginate();
          },

해당코드를 사용 하려 하는데요

근데 이렇게 포스리펫치를 삭제 하게 되면

[홈] 메뉴와 [음식] 메뉴에서는 정상적으로 REQ RES 포스트 겟 요청이 가는데

[주문] 메뉴에서는 아무런 응답이 없어서 새로고침이 되지 않습니다.

 

현재 강의에서 장바구니에서 주문완료를 눌러도 장바구니 내용이 비워지지 않는 문제와

로딩이 이중으로 되는 문제를 확인했는데

장바구니 부분은 주문완료버튼을 눌렀을때 주문내용을 비워버리면 해결 될 것 같다는 개념이라도 잡히는데

포스리펫치 부분은 어디서 손을 대야 될지 아직 개념이 잡히지 않는데요

 

홈메뉴와 음식메뉴에서는 forceRefetch:true가 아니더라도 서버에서 자료를 받는 로직이 있는데

주문메뉴에서는 앱에서 발생된 주문건에 대해서만 받아오는 로직이라 그게 아닌가? 싶은 생각만 듭니다.

1.앱을 처음 로딩해서 주문메뉴에 들어갔을때 -> 로딩이 강제로 되니 새로운 주문건이 화면에 표시됨

2.포스리팻치 true일경우 -> 강제 새로고침기능이 작동하니 새로운 주문건이 화면에 표시됨

3.포스리팻치를 삭제하고 리프레쉬인디게이터만 사용할경우 -> 새로운 주문건이 표시가 안됨.

 

어떤 부분을 확인하거나 살펴보는게 좋을지 힌트를 주셨으면 좋겠습니다.

만일 forceRefetch:true를 꼭 사용해야 되는 설계라면

로딩바 대신에 스켈레톤을 사용한다면 2중 로딩느낌이 안날 것 같다는 생각이 듭니다.

답변 1

0

코드팩토리님의 프로필 이미지
코드팩토리
지식공유자

안녕하세요!

로딩이 이중으로 된다는게 무슨 말씀이신지 잘 모르겠습니다.

예제 코드나 스크린샷을 보여주실 수 있을까요?

1번 2번이 잘 되는데 왜 3번을 해야하는지도 잘 이해가 안됩니다.

추가 정보 전달주시면 답변 해드리도록 하겠습니다!

감사합니다!

GO님의 프로필 이미지
GO
질문자

로딩이 이중으로 된다는 표현은 -

상단에 refreshIndicator 를 통해 [뱅글뱅글 도는 로딩]표시가 생기는데

화면이 한번 갱신이 되면서 화면중앙에 circuralIndicator[뱅글뱅글 도는로딩] 표시 가 또 한번 보여진다는 것을 말씀드린 것입니다.

로딩인디게이터1 -> refreshIndicator

로딩인디게이터2 -> circuralIndicator

강의에서 선생님께서는 극단적인 효과를 얻기위해서 forceRefetch:true 를 하시겠다 설명을 하시는데요. 로딩표시 인디게이터가 2번 사용되니 로딩바 역시 2번 보이는 것 보다 한쪽만 사용하는게 낫겠다 싶었고

당겼을때 새로고침 기능을 하는 - refreshIndicator를 사용할때에는 사용목적상 우선이 되니 circuralIndicator는 표시 안되는게 좋겠다는 생각에 forceRefetch:true를 삭제하는 코드를 사용하고 싶었던 것입니다. 강의에서도 삭제해도 된다고 설명을 하시구요.

그런데

홈, 음식 탭에서는 forceRefetch:true를 삭제하고 refreshIndicator만 사용해도, 응답요청이 들어가서 새로운 자료가 보이게 설계가 되어있는데

주문 탭에서는 forceRefetch:true를 삭제하면, refreshIndicator 는 작동하지만 새로운 주문을 확인하는 응답이 들어가지 않기 때문에

어떤 부분을 확인 해야될지 문의를 드려 본 것입니다.

 

예를 들어 홈,음식탭에는 forceRefetch:true를 사용하지 않고 refreshIndicator로만 응답요청이 가는데 이 로직을 담당하는 부분을 주문탭에도 넣을 수 있게 하려면 어떤구간을 살펴봐야 될지,

또는 refreshIndicator 사용할때 forceRefetch:true를 사용하는 것이 아닌 아닌 refreshIndicator 자체적으로 새로고침을 하는 코드를 넣어서 새로고침기능을 가진다든지 등의 방법이 있다면

어떤 부분을 참고해야 될지 현재로는 감이 안오니 체크를 부탁 드리는 것입니다.

 

요점은 홈,음식 탭에서는 refreshIndicator(forceRefetch:true 삭제) 만 사용해도 새로고침 요청이 서버로간다. 주문탭은 refreshIndicator 만 사용하면 새로운 주문완료건이 갱신되지 않는다 입니다.

코드팩토리님의 프로필 이미지
코드팩토리
지식공유자

안녕하세요!

이해하고 계신대로 forcerRefetch: true를 넣지 않으면 강제 리프레시 요청이 안들어가는 로직이기 때문에 새로고침이 안됩니다.

단순히 refresh indicator가 돌고 circular progress indicator가 다시 도는 UI 현상을 막고싶은거라면 forceRefetch를 했을때 기존에 데이터가 있었는지 없었는지 확인하면 될 것 같습니다.

그리고 기존 데이터가 있는 상태의 상속 클래스를 하나 더 만들어서 해당 클래스의 인스턴스가 전달되면 중앙 로딩은 안보이게 하면 될 것 같습니다. (아마 refresh indicator를 안보이게 하는건 말이 안되겠죠?)

제가 잘 이해한게 맞을까요?

감사합니다!

GO님의 프로필 이미지
GO
질문자

네 당겼을때 새로고침을 했을때는 상단의 refreshIndicator 만 뱅글뱅글 돌고, 중앙의 circuralIndicator 는 다시 표시가 안됐으면 좋겠습니다. 무엇보다 forceRefetch:true 가 동작하게 되면 화면 자체가 새로고침 되는데요, 열심히 캐싱 기능을 만들었는데 다시 첫로딩을 하는것 같은 느낌이 드는 것 같습니다.

일단 아직 강의를 2번밖에 안봐서 이해가 잘 안되지만, 선생님 말씀 참고하면서 강의를 몇번 더 반복해서 보면서

홈,음식 탭에서 forceRefetch:true 를 삭제해도 응답요청이 가는 로직을 찾아서(섹션9의 페이지네이션 구간인 것 같은데;; )

주문탭에도 적용할 수 있는 방법을 한번 고민 해보겠습니다.

강의준비하시느라 수고 많으실텐데 감사합니다~!

코드팩토리님의 프로필 이미지
코드팩토리
지식공유자

그렇다면 아마도 제가 정확히 이해하고 답변 드린 것 같습니다. 제가 말씀드린대로 한번 도전해보시고 (성공하시면 아마 다신 안잊으실겁니다) 도저히 못하겠으시면 다시한번 질문 주세요!

GO님의 프로필 이미지
GO
질문자

선생님 중급강의 3번째 듣는중 해당위치에 또 와버려서;; 문제 해결을 위해 노력을 한 결과물을 전달 드려보겠습니다.


일단 기존의 이중 로딩 문제는 해결하지 못했습니다.

홈 메뉴, 음식 메뉴 모두 paginate 함수를 통해 리프레쉬 인디게이터로도 GET요청이 들어가서 새자료를 받아볼 수 있는데

주문메뉴 에서는 첫 로딩시 , forceRefetch:true 가 작동을 할때만 새로운 주문건이 화면에 표시되는 문제를 제 수준에서는 해결을 못하겠습니다.

그래서..

장바구니에서 (결제완료 버튼)을 누르면

1.기존 장바구니 비우기

2. 주문완료건 미리 새로고침 해두기

를 목표로

basket_screen.dart 파일내의 주문완료 버튼의 onPressed : 코드내에서

onPressed: () async {
  final resp = await ref
    .read(orderProvider.notifier)
    .postOrder();
  if (resp) {
    context.goNamed(OrderDoneScreen.routName);
    // 1.결제하기버튼을 눌러 정상적으로 결제가 되면 바스켓프로바이더 비워버리기
    ref.read(basketProvider.notifier).state.clear();
    // 2.orderProvider의 forcRefetch:true를 강제로 작동시켜버리기
    ref
       .read(orderProvider.notifier)
       .paginate(forchRefetch: true);
  } else {
    ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(content: Text('결제 실패!')));
  }
},

위와 같은 방법으로

a. 바스켓프로바이더를 비워서 장바구니를 삭제

b. 결제하기 버튼이 작동되면 미리 orderProvider를 forRefetch:true 시켜서 주문 메뉴를 갱신했습니다.

위코드로 기존 장바구니가 비워졌고 주문확인 메뉴에서 새로고침을 할필요 없이 결제가 되면 주문이 추가되는 방식으로 어쨌든 겉보기엔 정상 작동은 하는데요

제가 뭘 제대로 알고 작업을 한 것 같진 않고;

아직 중급강의 중후반부를 넘어가면 어려워서 현재로선 이런 꼼수? 코드가 최선 인 것 같습니다.

아무튼 더 열심히 해보겠습니다

 

코드팩토리님의 프로필 이미지
코드팩토리
지식공유자

제가 위에서 말씀드린대로 해보시는건 어떨까요? Refresh를 직접 한 경우 클래스 상태를 하나 더 만들어서 해당 클래스가 반환되면 중앙 CircularProgressIndicator가 안보이게 하시면 됩니다.

GO님의 프로필 이미지
GO

작성한 질문수

질문하기