สร้างแอพ Counter แบบ MVP (Model View Presenter) โดยทุกครั่งที่กดปุ่ม ตัวเลขก็จะเพิ่มขึ้นเรื่อยๆ

MVP – Model View Presenter
- View: The views are responsible for deciding how the data is to be displayed to the user. Normally the view is the Activity or Fragment
- Presenter: This is the brain of the app. All the business logic is kept here. It is responsible for keeping the view and model away from each other. View and Model can only talk through the Presenter.
- Model: This is the data centre of the app. All the data is kept here and when the model is changed, instead of updating the view directly, the presenter is notified to update the views accordingly.
สร้างโปรเจ็กส์ชื่อ Counter โดยจะมีไฟล์ต่างๆดังนี้

1.สร้าง Interface ชื่อ ContractInterface

ContractInterface.kt
package com.phaisarn.counter.contract interface ContractInterface { interface Model { fun getCounter(): Int fun incrementCounter() } interface View { fun initView() fun updateViewData() } interface Presenter { fun getCounter(): String fun incrementValue() } }
2.สร้าง Class ชื่อ MainActivityModel

MainActivityModel.kt
package com.phaisarn.counter.model import com.phaisarn.counter.contract.ContractInterface.* class MainActivityModel : Model { private var mCounter = 0 override fun getCounter() = mCounter override fun incrementCounter() { mCounter++ } }
3.สร้าง Class ชื่อ MainActivityPresenter
MainActivityPresenter.kt
package com.phaisarn.counter.presenter import com.phaisarn.counter.contract.ContractInterface.* import com.phaisarn.counter.model.MainActivityModel class MainActivityPresenter(_view: View) : Presenter { private var view: View = _view private var model: Model = MainActivityModel() init { view.initView() } override fun getCounter() = model.getCounter().toString() override fun incrementValue() { model.incrementCounter() view.updateViewData() } }
4.สร้าง Class ชื่อ MainActivity
ลบคลาส MainActivity เดิมและสร้าง Class ชื่อ MainActivity ขึ้นมาใหม่ (หรือจะ Move แล้วเหลี่ยนชื่อ package เอาก็ได้)
MainActivity.kt
package com.phaisarn.counter.view import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import com.phaisarn.counter.R import com.phaisarn.counter.contract.ContractInterface.* import com.phaisarn.counter.presenter.MainActivityPresenter import kotlinx.android.synthetic.main.activity_main.* class MainActivity : AppCompatActivity(), View { private var presenter: MainActivityPresenter? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) presenter = MainActivityPresenter(this) } override fun initView() { counterTextView.text = presenter?.getCounter() clickButton.setOnClickListener { presenter?.incrementValue() } } override fun updateViewData() { counterTextView.text = presenter?.getCounter() } }
5.แก้ไขไฟล์ activity_main.xml
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".view.MainActivity"> <LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent"> <TextView android:id="@+id/counterTextView" android:layout_width="match_parent" android:textSize="72sp" android:textAlignment="center" android:layout_height="wrap_content"/> <Button android:id="@+id/clickButton" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="36dp" android:layout_gravity="center" android:text="Counter"/> </LinearLayout> </androidx.constraintlayout.widget.ConstraintLayout>
6.แก้ไขไฟล์ AndroidManifest.xml
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:dist="http://schemas.android.com/apk/distribution" package="com.phaisarn.counter"> <dist:module dist:instant="true"/> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".view.MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> </application> </manifest>