• 카테고리

    질문 & 답변
  • 세부 분야

    모바일 앱 개발

  • 해결 여부

    미해결

화면새로고침 질문.

22.09.27 16:56 작성 조회수 1.1k

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

질문자

2022.09.28

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

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

chorokdosi님의 프로필

chorokdosi

질문자

2022.09.28

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

질문자

2022.09.29

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

시도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

질문자

2022.09.29

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

질문자

2022.09.29

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

@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

질문자

2022.09.29

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

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

chorokdosi님의 프로필

chorokdosi

질문자

2022.09.29

  @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

질문자

2022.09.29

@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

질문자

2022.09.29

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번이라 바로 보이는 화면으로 되어있습니다.

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