RIBs Architecture tutorial

RIBs Architecture tutorial

RIBs 에 대한 깊은 이해가 아직 부족하지만, 처음 Architecture 를 접하는 사람들에게 psuedo code 와 함께 빠른 이해를 돕고자 적어보았다 (+정리하며 다시 복습하기 위해) 차후에 이해도가 높아진다면 이 글을 다시 쓰게 될 지도 모르겠다 :(

RIBs?

ribs logo

RIBs & Android

iOS 알못이라… 정확히 어떤 부분이 Activity, Service 를 대체하는지는 모르겠다. 다만 Cross Architecture 을 위한 로직을 목적으로하는 만큼 위와 같은 platform dependent 한 요소에 의존하는 것을 지양하고자 한다.

RIB 이란?

ribs architecture

RIBs 는 앱 전체의 상태를 트리 형태로 나타낸다. 이때 이 트리의 각 노드들을 RIB(Router, Interactor, Builder) 이라고 한다.

RIB 은 이름 처럼 다양한 Components 들로 이루어져 있다. 우선 각각의 노드가 어떤 역할을 하는지 확인해보자.

Components

  1. Interactor
class HappyInteractor {

    // Interface for ascending RIBs
    @Inject var listener: Listener
    // Interface for current Interactor's view(=presenter)
    @Inject var presenter: HappyPresenter

    fun didBecomeActive() {
        // Handle reactive subscribtion
        presenter.routeChildRibButtonClick()
            .subscribe {
                getRouter().attachChildRouter()
            }

        presenter.routeSiblingRibButtonClick()
            .subscribe {
                listener.changeRouting()
            }

        stateFromParentRIBs
            .subscribe {
                if (it === "happy") {
                    presenter.setHappyFace(true)
                } else {
                    presenter.setHappyFace(false)
                }
            }
    }
}
  1. Router
class HappyRouter(
    val childRibBuilder: ChildRibBuilder
) {
    var childRouter: ChildRouter? = null

    fun attachChildRouter() {
        childRouter = childRibBuilder.build()
        attachChild(childRouter)
        getView().addView(childRouter.getView())
    }

    fun detachChildRouter() {
        childRouter?.let {
            detachChild(it)
            getView().removeView(it.getView())
        }
        childRouter = null
    }
}
  1. Builder
class HappyBuilder {

    fun build(parentArgs: ParentArgs): HappyRouter {
        val component = DaggerHappyBuilder_Component.builder()
            .dataFromParent(parentArgs)
            .interactor(HappyInteractor())
            .build()

        return component.happyRouter()
    }

    // Code of Providers, Modules, Components ....
}
  1. View + Presenter (Optional)
class HappyView: View(), HappyPresenter {
    // ...
    val happyButton: Button
    val emojiText: TextView

    fun buttonClick(): Observable<Unit> =
        RxView.clicks(happyButton)

    override fun setHappyFace(happy: Boolean) {
        if (happy) {
            emojiText.text = ":)"
        } else {
            emojiText.text = ":("
        }
    }
}

Back to RIBs

ribs state tree