강의

멘토링

커뮤니티

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

chorokdosi님의 프로필 이미지
chorokdosi

작성한 질문수

Flutter 초급 - Http통신, 상태관리

화면새로고침 질문.

작성

·

1.5K

0

커뮤니티 앱을 만들고 있습니다. 그런데 막히는 부분이 있어서 질문드립니다.

글작성 버튼 클릭 후 화면이동 후 목록화면에서 화면을 그릴때 새로운 데이터(DB)가 있으면 바로 그려서 보여줘야하는데 그러지못하고있습니다.

상태관리를 하면 될거같은데 어떤식으로 해야할지모르겠습니다.

 RefreshIndicator(
  onRefresh: () async {
    setState(() => communityViewModel.onEvent(CommunityEvent.community_query()));
    await Future.delayed(Duration(seconds: 3));
  },

스크롤을 내렸을때 새로운데이터를 가져오는 것은 이런식으로 코드작성하니 새로운 데이터를 가져옵니다.

답변 1

0

오준석님의 프로필 이미지
오준석
지식공유자

화면을 이전 화면으로 돌아갈 때 Navigator.push 와 pop 을 사용하여 어떤 값을 전달할 수 있습니다.

글 작성 완료와 같은 의미의 데이터를 돌려준 후에 그 값에 따라서 데이터를 다시 읽어오시면 됩니다.

다음 링크를 참고해 보세요.

https://docs.flutter.dev/cookbook/navigation/returning-data

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

글목록페이지와 글작성페이지가 BottomNavigationBar로 화면 이동 중에 있습니다. 그러면 글작성페이지에서 버튼클릭시에 값을 넣어서 넘겨줘야 할까요?

오준석님의 프로필 이미지
오준석
지식공유자

그럼 그냥 글목록페이지의 initState() 에서 목록을 가져와야 할 것 같습니다

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

initState()에서 communityViewModel.onEvent(CommunityEvent.community_query())를 호출하면 에러가 발생합니다.

dependOnInheritedWidgetOfExactType<_InheritedProviderScope<CommunityViewModel?>>() or dependOnInheritedElement() was called before _HomeCommunityPageState.initState() completed.

역시 저렇게 호출하면 안될거같은데 어떻게 불러와야할까요?

오준석님의 프로필 이미지
오준석
지식공유자

initState() 에서 ViewModel 을 부를때 context를 사용한다면 Future.microtask 같이 약간의 딜레이가 필요합니다.

image

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

아하 그렇군요 참고해서 시도 했는데 여전히 오류가 발생합니다.

시도1 .

Future.microtask(() => communityViewModel.onEvent(CommunityEvent.community_query())
);

시도 2.

Future.microtask(() => context.read<CommunityViewModel>().notifyListeners()
);

시도3

Future.microtask(() => Provider.of<CommunityViewModel>(context, listen:  false).notifyListeners()
);

 시도4

Future.microtask(() => context.read<CommunityViewModel>().onEvent(CommunityEvent.community_query())
);

이런식으로 적는게 아닌건가요?

오준석님의 프로필 이미지
오준석
지식공유자

혹시 communityViewModel 은 Provider로 관리되고 있는 것이 아닌가요? Provider라는 가정하에 설명드렸습니다.

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

communityViewModel 클래스 내용은 강사님 유튜브참고해서 만들었습니다. 그러면 제 communityViewModel 클래스는 Provider가 관리중이 아닌건가요?

ChangeNotifierProvider.value(
  value: CommunityViewModel(CommunityRepositoryImpl(CommunityApi()))
),

 

오준석님의 프로필 이미지
오준석
지식공유자

핸드폰으로 볼 때 시도 2까지 보였는데 시도 4까지 있었네요. 시도4가 맞습니다.

오준석님의 프로필 이미지
오준석
지식공유자

생각해보니 BottomNavigationBar 생성할 때 이미 화면 2개를 생성해서 연결한 상태일테니 initState() 에서 새로고침하는 것이 의미가 없어보입니다.

화면이 보일 때 새로고침을 해야할 것 같은데 onResume 상태를 알아야 할 것 같습니다. 다음을 참고하시면 화면 보일때를 알 수 있을겁니다.

https://stackoverflow.com/questions/44331725/onresume-and-onpause-for-widgets-on-flutter

https://blog.naver.com/chandong83/222106016536

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

감사합니다. 혹시 이렇게 사용하는게 맞나요?

@override
void initState() {
  print('home initState');
  _animationController = new AnimationController(vsync: this)
  ..repeat(min: 0.0, max: 1.0, period: Duration(seconds: 1))
  ..addListener(() {
    print('animation');
    Future.microtask(() => context.read<CommunityViewModel>().onEvent(CommunityEvent.community_query())
    );
  });
  //WidgetsBinding.instance.addObserver(this);
  super.initState();
}

Run에 계쏙 출력되는데 문제있는거 아닌가요? 새로고침은 됩니다.

오준석님의 프로필 이미지
오준석
지식공유자

이 코드는 1초마다 새로고침을 수행하는 코드입니다.

네트워크를 사용하거나 한다면 문제가 있는 코드이겠지요.

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

아하 그러면 사용하면 안되겠네요? WidgetsBindingObserver사용해야하는건가요?

오준석님의 프로필 이미지
오준석
지식공유자

네. 이 방법이 유일할 것 같습니다.

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

  @override
  void initState() {
    print('home initState');
    WidgetsBinding.instance.addObserver(this);
    super.initState();
  }

  @override
  void dispose() {
    print('home dispose');
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

@override
void didChangeAppLifecycleState(AppLifecycleState state) {
  print('home didChangeAppLifecycleState');
  super.didChangeAppLifecycleState(state);

  switch (state) {
    case AppLifecycleState.resumed:
      Future.microtask(() => context.read<CommunityViewModel>().onEvent(CommunityEvent.community_query())
      );
      print('resumed');
      break;
    case AppLifecycleState.inactive:
      Future.microtask(() => context.read<CommunityViewModel>().onEvent(CommunityEvent.community_query())
      );
      print('inactive');
      break;
    case AppLifecycleState.paused:
      Future.microtask(() => context.read<CommunityViewModel>().onEvent(CommunityEvent.community_query())
      );
      print('paused');
      break;
    case AppLifecycleState.detached:
      Future.microtask(() => context.read<CommunityViewModel>().onEvent(CommunityEvent.community_query())
      );
      print('detached');
      break;
  }
}

paused에만 호출하면 될거같은데 이렇게 사용하는거 맞나요? 일단 didChangeAppLifecycleState가 글작성후 왔을때 실행이 안되네요.

오준석님의 프로필 이미지
오준석
지식공유자

잘 작성된 것 같은데요.

paused는 화면이 안보여질 때이고, resumed 는 보여질 때 이므로 resumed 에만 호출하면 됩니다.

참고로 Future.microtask 는 initState() 에서만 사용하면 되므로 삭제해도 됩니다.

이론적으로는 화면 왔다갔다 할 때 각 라이프사이클마다 print 가 동작되어야 합니다.

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

@override
void initState() {
  print('home initState');
  Future.microtask(() => context.read<CommunityViewModel>().onEvent(CommunityEvent.community_query())
  );
  WidgetsBinding.instance.addObserver(this);
  super.initState();
}

@override
void dispose() {
  print('home dispose');
  WidgetsBinding.instance.removeObserver(this);
  super.dispose();
}

@override
void didChangeAppLifecycleState(AppLifecycleState state) {
  print('home didChangeAppLifecycleState');
  super.didChangeAppLifecycleState(state);
  switch (state) {
    case AppLifecycleState.resumed:
      print('resumed');
      break;
  }
}

코드 수정했습니다. 그런데 글작성후 아무런 변화가 없습니다. 하단탭바로 이동시에만 새로고침이 됩니다.

오준석님의 프로필 이미지
오준석
지식공유자

지금은 resumed 에 로딩하는 코드가 없는데 새로고침이 되나요? initState() 에는 있을 필요가 없고 라이프사이클 쪽으로 코드가 와야 될 것 같은데요.

그리고 이 방법은 BottomNavigationBar 에서 탭 이동시에 새로고침을 하게 하는 방법입니다.

글 작성후는 어떤 상황인지 저는 전혀 인지하고 있지 않아서 답변이 어렵습니다.

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

resumed 로딩하는 코디가 따로 있나요? 지금상태에서는 글작성 후 didChangeAppLifecycleState 호출이 안되더라고요

void initState() {
  print('home initState');
  WidgetsBinding.instance.addObserver(this);
  super.initState();
}

@override
void dispose() {
  print('home dispose');
  WidgetsBinding.instance.removeObserver(this);
  super.dispose();
}

@override
void didChangeAppLifecycleState(AppLifecycleState state) {
  print('home didChangeAppLifecycleState');
  super.didChangeAppLifecycleState(state);
  switch (state) {
    case AppLifecycleState.resumed:
      context.read<CommunityViewModel>().onEvent(CommunityEvent.community_query());
      print('resumed');
      break;
  }
}

글작성페이지에서 글작성버튼클릭하면 BottomNavigationBar있는 클래스로 이동하게 했습니다.

이동된페이지에는 예전데이터만 보이고 있습니다.

BottomNavigationBar있는 클래스에서 글목록페이지 list에서 1번이라 바로 보이는 화면으로 되어있습니다.

오준석님의 프로필 이미지
오준석
지식공유자

장면이 정확히 이해는 안 되지만, 어쨌든 이 코드는 이 화면이 보이는 순간마다 새로고침을 하는 로직입니다.

chorokdosi님의 프로필 이미지
chorokdosi

작성한 질문수

질문하기