//View 와 Presenter 인터페이스를 소유한 Contract 인터페이스
interface Contract {
interface View {
fun showNewItem(item: String)
}
interface Presenter {
var view: View
var model: Model
fun requestItem()
}
}
/*
* Presenter 는 View 와 Model 사이에 존재하며
* View 에서 특정 이벤트가 발생하면 Presenter 는 Model 에게 데이터를 요청하고
* Model 은 Presenter 에게 Remote 또는 Local 데이터를 전달한다
* Presenter 는 Model 에서 전달받은 데이터를 View 에게 전달하고
* View 는 데이터를 UI 에 반영한다.
* */
class Presenter : Contract.Presenter {
//Presenter 는 View 와 Model 사이에서 징검다리 역할을 하므로 두 객체를 모두 소유하고 있다.
override lateinit var view: Contract.View
override lateinit var model: Model
constructor(view: Contract.View) {
this.view = view
model = Model()
}
override fun requestItem() {
val newItem = model.getItem()
view.showNewItem(newItem)
}
}
/*
* Model 은 Repository 를 통해 Remote 또는 Local 데이터를 얻으며
* 얻은 데이터를 Presenter 에게 반환해준다.
* */
class Model {
fun getItem(): String {
return Repository.responseLocalData()
}
}
class MainActivity : AppCompatActivity(), Contract.View {
private val recyclerView: RecyclerView by lazy {
findViewById(R.id.recyclerView)
}
private val fab: FloatingActionButton by lazy {
findViewById(R.id.fab)
}
private lateinit var adapter: RecyclerViewAdapter
private val itemList: MutableList<String> = mutableListOf()
private var presenter: Contract.Presenter? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
presenter = Presenter(this)
initViews()
}
private fun initViews() {
adapter = RecyclerViewAdapter(itemList)
recyclerView.layoutManager = LinearLayoutManager(this)
recyclerView.adapter = adapter
//Floating Action Button 에 클릭 이벤트가 발생하면
//Presenter 에게 알리며 Presenter 는 Model 에게 데이터를 요청한다.
fab.setOnClickListener {
presenter?.requestItem()
}
}
//Presenter 가 Model 에게 데이터를 받은 후 View 에 해당 데이터를 전달하면
//View 는 해당 메서드를 통해 UI(RecyclerView) 에 반영한다.
override fun showNewItem(item: String) {
itemList.add(item)
adapter.notifyDataSetChanged()
}
}
View는 Presenter를 통해서만 데이터에 접근하므로 View와 Model 사이의 의존성이 사라진다.
View와 Presenter는 1:1 관계를 맺게되며 View를 하나 추가할 때 마다(ex: Activity 추가) 그에 맞게 Presenter도 하나씩 추가해서 정의해줘야한다.