LoginSignup
2
0

More than 3 years have passed since last update.

[Android] Kotlin の sealed class でステートマシン

Last updated at Posted at 2021-02-10
class MainFragment : Fragment(R.layout.main_fragment) {

    override fun onResume() {
        super.onResume()

        lifecycleScope.launch {
            // 命令を与える例
            MainFragmentState.currentState.onHoge(this@MainFragment)

            // 現在のステータスを確認する例
            when {
                MainFragmentState.currentState.isIdle() -> {}
                MainFragmentState.currentState.isState1() -> {}
                MainFragmentState.currentState.isState2() -> {}
            }
        }
    }

    sealed class MainFragmentState {
        private object Idle : MainFragmentState() {
            override suspend fun onHoge(mainFragment: MainFragment) {
                // do something..
                delay(3_000)
                changeState(mainFragment, State1)
            }
        }

        private object State1: MainFragmentState() {
            override suspend fun enter(mainFragment: MainFragment) {
                // do something..
                delay(3_000)
                changeState(mainFragment, State2)
            }
        }

        private object State2: MainFragmentState(){
            override suspend fun enter(mainFragment: MainFragment) {
                // do something..
                delay(3_000)
                changeState(mainFragment, Idle)
            }
        }

        protected open suspend fun enter(mainFragment: MainFragment) {} // ステータス開始時の処理
        protected open suspend fun exit(mainFragment: MainFragment) {} // ステータス終了時の処理
        protected suspend fun changeState(mainFragment: MainFragment, nextState: MainFragmentState) {
            this.exit(mainFragment)
            // 裏でステータスが変わっている場合、または、次が同じステータスの場合は何もしない
            if (currentState != this || nextState == this) return
            currentState = nextState // 保持しているステータスを上書き
            nextState.enter(mainFragment)
        }

        // 外からの命令郡
        open suspend fun onHoge(mainFragment: MainFragment) {}
        open suspend fun onFuga(mainFragment: MainFragment) {}
        open suspend fun onPiyo(mainFragment: MainFragment) {}

        // 外からの命令で、どのステータスでも共通の処理はここにロジックを書いてしまう
        @CallSuper // 継承を許す場合は open にして @CallSuper アノテーションを付与しておく
        open suspend fun init(mainFragment: MainFragment) {
            changeState(mainFragment, Idle)
        }

        // サブクラスは外へ公開していないので、確認用のメソッドを別途用意
        fun isIdle(): Boolean = this is Idle
        fun isState1(): Boolean = this is State1
        fun isState2(): Boolean = this is State2

        companion object {
            // ここにステータスを保持する
            var currentState: MainFragmentState = Idle // 初期値
                private set // 外からの更新は禁止
        }
    }
}
2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0