https://blog.naver.com/ssarang8649/220948756167
이전 포스팅에서
안드로이드 타이머의 기초에 이어
이번에는 주기적으로 메서드를 실행하다가
중간에 잠깐 타이머를 중지한 후 다시 실행하는 기능이 필요해서 구현해보려합니다.
본 포스팅에서 확인하실 수 있는 정보는
안드로이드 타이머 중지 후 재시작 할 때 유의 사항
입니다.
이전 포스팅에서
안드로이드 타이머를 작동시키기 위해서는
1. 타이머 클래스 (Timer) 가 필요하고
2. 타이머가 하게될 일 즉 타이머 태스크 (TimerTask)
이 두가지가 필요하다는 것을 알 수 있었습니다.
하나의 타이머로
2개의 일을 할 수 있게 스케쥴링 할 수도 있는데요.
이전 코드에서
Timer 객체인 timer를 선언했고
이 timer에 3초에 1번씩 counter1을 올리도록 구현했었는데
여기에 또 하나의 TimerTask 객체인 tt2와 counter2 를 선언해서
이번엔 1초마다 tt2 를 실행하도록 추가하겠습니다.
이때 tt2가 하는일(Task)는 counter2 를 2개씩 올리는 것입니다.
하나의 timer객체의 2개의 스케쥴이 확인하실 수 있습니다.
실행해보면..
아래와 같이 3초에 1번 counter1 을 1씩 올리는 tt 타이머태스크와
1초에 1번 counter2를 2씩 올리는 tt2 타이머 태스크가
동시에 작동하는것이 보입니다.
그렇다면 이렇게 걸린 스케쥴을 중지하고 싶을땐 어떻게 하느냐
그것을 위해 TimerTask 클래스는
cancel() 메서드를 제공합니다.
딱 3개 메서드 밖에 없네요...
cancel() : 타이머 태스크를 취소(중지)합니다.
run() : 타이머 태스크에서 정의한 run 메서드를 실행합니다.
scheduledExecutionTime() : 해당 타이머 태스크가 마지막에 실행한 시간을 timestamp 로 리턴합니다.
TimerTask 를 중지하고 재시작을 테스트해보기 위해
버튼을 2개 추가해보겠습니다.
그리고 버튼 이벤트에서 Timer 를 활용할 수 있도록 final 로 선언합니다.
STOP 버튼을 누르면
tt (counter1을 1개씩 증가하는 Task) 를 cancel 한다음 마지막 실행시간을 출력하게 하고
START 버튼을 누르면 정지한 스케쥴을 다시 구동하는 것이 목표입니다.
Stop을 누르면
위와 같이 1개의 Task 가 중지되어서
tt2 만 살아있는것을 볼 수 있습니다.
이제 Start 버튼을 누르면 마법처럼 다시 tt 가 살아나서 다시 3초에 1번씩 출력되야 하는는데요
Start를 누르면
java.lang.IllegalStateException: TimerTask is scheduled already
에러를 뱉으며 멋지게 뻗어버립니다. ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ
여기서 결론
한 번 Cancel 한 TImeTask 는 다시 스케쥴 할 수 없습니다. (재사용이 불가합니다.)
그렇다고 해서 Cancel 한 TimeTask 가 아예 사라진 것(Terminated)도 아닙니다.
아래와 같이 cancel 한 tt의 run() 메서드를 실행하도록 한다음
조낸 Stop 버튼을 눌러보면
위처럼 1번 태스크는 아직 건재합니다.
그래서 Timer 쪽에서 스케쥴 했떤 TimeTask 의 기억을 지울 수 있을지 한번 찾아봅니다.
오! purge()라는 메서드가 있네요
타이머의 task queue 에서 cancel된 Task들을 다 지워버린답니다.
그러면 지운다음에 한번 시도해 볼까요 (위 코드에서 이미 있었던 purge를 살려봅니다)
Stop 버튼을 2번 누르니
tt가 cancel 되고 곧 바로 timer 객체의 purge 메서드가 실행되면서
cancel 된 tt를 taskQueue 에서 지웁니다.
1개가 지워졌다고 출력되고 한번 더 누르니 이미 지워져 0개 지웠다고 출력하네요.
자 이제!! Start버튼을 누르면 되겠지
다시 적나라하게 뻗어버립니다...ㅋㅋㅋㅋ
메시지는 동일하네요
java.lang.IllegalStateException: TimerTask is scheduled already
타이머 태스크가 이미 스케쥴 되었다는 에러 메시지입니다.
여기서 다시 결론
한 번 Cancel 한 TImeTask 는 다시 스케쥴 할 수 없습니다. Timer.purge() 해도 안됩니다.
(무조건 재사용이 불가합니다.)
아니 그럼 purge를 왜 만든거지..
개발 사이트에서 설명을 보면 purge는 거의 쓰지 않을것이라고 예언합니다.
왜냐면 timer 하나에 여러개 TimerTask 가 스케쥴 되어있을 경우
이미 cancel 한 Task 를 Queue에서 꺼내 Queue 공간을 낭비하지 않도록 하는 역할만 하기 때문입니다......
그렇다면
TimerTask 가 살아 있으니 다른 Timer를 선언해서 사용하면 될까?
라는 생각으로
해도 똑같습니다.
즉 TimerTask 를 재사용하기 위해서는 TimerTask 객체를 새로 생성해야합니다.
왜 이리 만들었는지는 java님이 알겁니다..
아무쪼록 재 사용이나 새로 만드는 거나 결국 메모리 사용량은 같을것이기 떄문이라고 생각하고 넘어갔습니다.
Background 에서 돌리는것도 해보려 했는데 그러고보니 왜 굳이
돌맹이 하나 재사용하려고 길을 하나 더 파나 하는 생각이 드네요...
따라서 스케쥴을 중지했다가 다시 실행시키려면
new TimerTask 정의 부분을 메서드로 변경해서
메서드를 실행할 때 마다 동일한 TimerTask 객체를 새로 만드면 됩니다.
심플하게 설명하기 위해 tt2는 지우고 1개의 task로 예를 들면 아래코드와 같습니다.
위와 같이 메서드를 정의해서 선언할 때마다 TimerTask 를 재생성해서 리턴하게 한 다음 사용하면
위와 같이 Stop 을 누르면 tt 가 cancel되었다가
Start 를 누르면 tt 객체가 초기화 되어 다시 timer 스케쥴에 걸림을 볼 수 있습니다.
내용이 어쩌다 보니 너무 길어졌는데
저와 같은 짓(?)을 하게될 어떤 분들이
삽질 시간을 줄이셨으면 합니다.
요약
TimerTask 는 어떻게든 재사용이 불가합니다. 재사용을 고민할 시간에 그냥 new 생성하세요 ㅎㅎ
도움 되신 분의 공감은 힘이 됩니다☆
궁금하신 점은 덧글 주시면 아는 한도에서 성심껏 답변드립니다^^
모두 화이팅 하세요~!!











