[android] RxJava를 이용해서 back 버튼 두 번 눌러야 앱 종료하기

출처: https://medium.com/rainist-engineering/handling-back-button-with-rxjava-d948d8d3db80

 

자주 가는 사이트에 올라온 구인글에 회사 기술블로그도 올라왔길래 가봤는데, 무려 예전에 RxJava 공부하려고 돌아다니다 들어갔던 사이트다 ㄷㄷ

그 땐 무슨 얘기인지 몰랐는데, 지금보니 이해가 간다.

 

중요한 부분은 buffer(count, skip) 였다.  count 만큼 쌓이면 넘겨주고, skip 만큼 날린다.

buffer(2, 1): 2개가 쌓이면 발행하고, 가장 오래된 1개를 지운다.

buffer(3, 2): 3개가 쌓이면 발행하고, 가장 오래된 2개를 지운다.

 

private Disposable backPressedDisposable;
private BehaviorSubject<Long> backPressedSubject = BehaviorSubject.createDefault(0L); // 생성할 때는 0을 넣는다

@Override
protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);

 backPressedDisposable = backPressedSubject
   .buffer(2, 1) // back 버튼을 한 번 누르면, 이전에 눌렀던 시간과 방금 누른 시간 2개의 값을 발행한다.
   .map(it -> new Pair<>(it.get(0), it.get(1))) // 비교하기 쉽게 Pair로 변환
   .map(pair -> pair.second - pair.first < TimeUnit.SECONDS.toMillis(2)) // 두 번째 누른 시간이 첫 번째 누른 시간보다 2초 이내인가
   .observeOn(AndroidSchedulers.mainThread())
   .subscribe(willFinish -> {
     if (willFinish) { // 2초 이내에 눌렀다면 종료
       finish();
     }
     else { // 아니면 toast 만 표시
       Toast.makeText(getApplicationContext(), "다시 누르면 종료함", Toast.LENGTH_SHORT).show();
     }
   });
}

@Override
public void onBackPressed() {
 backPressedSubject.onNext(System.currentTimeMillis()); // 눌린 시간 비교를 위해 현재 시간을 넣는다
}

@Override
protected void onDestroy() {
 super.onDestroy();

 try {
   backPressedDisposable.dispose();
 } catch (Exception ignore) {}
}