안드로이드 앱으로 디버깅중 얘를 스와이프로 강제 종료했는데 플러터에선 안드로이드의 라이프사이클을 인식 못하는 듯 보였다.
만약 스와이프를 통해 사용자가 강제 종료를 한다면 widget이 사라진 것으로 인식 되지 않아 flutter에선 deteched() 조차 하지 않음
그냥 Pause()로 안다.
그래서 우리가 할 것은 네이티브 앱과의 method Channel 이 있지만 결국 우리가 알고 싶은 것은 스와이프 강제종료시에deteched 를 감지하는 것이기에
void dispose() {
super.dispose();
exit(0);
}
을 해주거나
안드로이드 manifest에 service 선언
<service
android:name="service.MyService"
android:stopWithTask="false" />
open class MyService : Service() {
override fun onBind(p0: Intent?): IBinder? {
return null
}
override fun onTaskRemoved(rootIntent: Intent?) {
//.. some code
Log.e("asd","#!# Service TaskRemoved")
stopSelf()
super.onTaskRemoved(rootIntent)
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
return super.onStartCommand(intent, flags, startId)
}
}
class MainActivity: FlutterActivity() {
private val CHANNEL = "user_main_body"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
startService(Intent(this,MyService::class.java))
}
}
참고로 oncreate에 해야 해당 activity의 쓰레드가 종료될 때 서비스에게 종료를 알릴 수 있어 좀 더 안정적이라 한다
이건 flutter 의 고질적 문제기에 네이티브의 힘을 빌려야 했다.
아래 글은.. method 채널을 써야함을 알기까지 나의 과정을 통해 알게 된..라이프사이클 관리 함수다.. 필요하신 분은 보고..사용토록..ㅎ..하
만약 필자와 같은 방식의 문제가아니라 widget이 지워졌을 때 상태관리라면 WidgetsBindingObserver 을 사용하도록 하자
class _LifecycleWatcherState
extends State<LifecycleWatcher>
with WidgetsBindingObserver {}
너무 길어져서 코드를 분리했는데
우리가 사용할 방법은
WidgetsBindingObserver 라는 Mixin 함수를 사용할 것이다
이를 사용하기 위해선
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this); // (2)
}
void dispose() {
WidgetsBinding.instance.removeObserver(this); // (3)
super.dispose();
}
widget 생성시 , 종료시에 추가 해제를 해주고
나머지는
void didChangeAppLifecycleState(AppLifecycleState state) {
switch (state) {
case AppLifecycleState.resumed:
// 앱이 표시되고 사용자 입력에 응답합니다.
// 주의! 최초 앱 실행때는 해당 이벤트가 발생하지 않습니다.
print("asdasd resumed");
break;
case AppLifecycleState.inactive:
// 앱이 비활성화 상태이고 사용자의 입력을 받지 않습니다.
// ios에서는 포 그라운드 비활성 상태에서 실행되는 앱 또는 Flutter 호스트 뷰에 해당합니다.
// 안드로이드에서는 화면 분할 앱, 전화 통화, PIP 앱, 시스템 대화 상자 또는 다른 창과 같은 다른 활동이 집중되면 앱이이 상태로 전환됩니다.
// inactive가 발생되고 얼마후 pasued가 발생합니다.
print("asdasd inactive");
break;
case AppLifecycleState.paused:
// 앱이 현재 사용자에게 보이지 않고, 사용자의 입력을 받지 않으며, 백그라운드에서 동작 중입니다.
// 안드로이드의 onPause()와 동일합니다.
// 응용 프로그램이 이 상태에 있으면 엔진은 Window.onBeginFrame 및 Window.onDrawFrame 콜백을 호출하지 않습니다.
print("asdasd paused");
break;
case AppLifecycleState.detached:
// 응용 프로그램은 여전히 flutter 엔진에서 호스팅되지만 "호스트 View"에서 분리됩니다.
// 앱이 이 상태에 있으면 엔진이 "View"없이 실행됩니다.
// 엔진이 처음 초기화 될 때 "View" 연결 진행 중이거나 네비게이터 팝으로 인해 "View"가 파괴 된 후 일 수 있습니다.
print("detached");
break;
case AppLifecycleState.hidden:
//TODO: Handle this case.
}
}
이런 식으로 상태관리를 해준다
detached : 앱이 여전히 flutter 엔진에서 호스팅되지만 모든 호스트 view에서 분리됩니다.
inactive : 앱이 비활성 상태이며 사용자 입력을 수신하지 않습니다.
paused : 앱이 현재 사용자에게 표시되지 않고 사용자 입력에 응답하지 않고 백그라운드에서 실행 중입니다.
resumed : 앱이 표시 되고 사용자 입력에 응답합니다. 앱 최초 실행때는 해당 이벤트가 발생하지 않습니다.
앱을 백그라운드로 실행했을 경우 : inactive -> paused
백그라운드에서 앱을 활성화 했을 경우 : resumed
앱을 종료했을 경우 : inavctive -> paused -> detached
-> 이건 서비스 등록을 했다던가, 직접 종료(exit(0)) 를 선언했다던가
결국 나의 목적은.. 이루지 못했으나 WidgetsBindingObserver라는 것을 알게 됐다는 것에 의의를 두기로 하자..