Implementasi MVP (Model-View-Presenter)


Hai semua, kali ini Saya akan coba bercerita sedikit tentang pengalaman Saya dalam mengimplementasikan salah satu pattern yang cukup banyak digunakan oleh developer android saat ini, yaitu MVP (Model-View-Presenter).

Menurut Wikipedia MVP adalah…

A derivation of the model–view–controller (MVC) architectural pattern, and is used mostly for building user interfaces

Dalam mengembangkan aplikasi android, terkadang kita sering menemukan masalah ketika melakukan handling terhadap lifecycle dari android itu sendiri. Disinilah peran MVP untuk mencoba menyelesaikan masalah tersebut. Lalu, apa sih bedanya MVC dengan MVP ???

MVC Diagram

Dalam MVC, Model ini dapat diartikan sebagai object entitas dalam sebuah aplikasi. Misalnya, pada aplikasi Social Media entitas-nya yaitu User. Sedangkan Controller dapat diartikan sebagai penghubung antara View dengan Model.

MVP Diagram

Perbedaan yang cukup signifikan yaitu pada pattern MVP View tidak disarankan untuk berkomunikasi langsung dengan Model melainkan harus melalui perantara atau bisa juga disebut dengan Contract (dalam hal ini Presenter bertugas hanya sebagai Interface antara Model dan View). Sedangkan pada pattern MVC, Controller dapat dimanfaatkan untuk melakukan proses business logic dari Model dan meneruskan nya langsung ke View.

Sudah cukup jelas ? Jika belum, Saya akan coba membuat aplikasi sederhana dengan memanfaatkan pattern MVP tersebut. Sebelum kita mulai, Saya harap pembaca sudah paham tentang dasar-dasar pemrograman di Android. Jika belum dapat memahami terlebih dahulu pada artikel berikut ini :)

Pertama, Kita membuat layout terlebih dahulu dengan nama activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:targetApi="LOLLIPOP">

<android.support.v7.widget.Toolbar
android:id="@+id/toolbar_main"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:background="@color/colorAccent"
android:elevation="4dp"
app:theme="@style/AppTheme.Toolbar" />

<FrameLayout
android:id="@+id/fl_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/toolbar_main" />

<Button
android:id="@+id/btn_main"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_margin="16dp"
android:paddingBottom="16dp"
android:paddingTop="16dp"
android:text="@string/btn_start"
android:textColor="@color/colorPrimaryDark"
android:textSize="16sp" />
</RelativeLayout>

Lalu, kita buat data model-nya dengan nama Data.java

public class Data {
private String text;

public Data() {
}

public String getText() {
return text;
}

public void setText(final String text) {
this.text = text;
}
}

Agar code Kita lebih clean, seperti biasa Saya akan membuat 2 buah Base Contract yang akan digunakan oleh View dan Presenter…

public interface View {
void onAttachView();

void onDetachView();
}

Berikutnya kita buat interface dari si Presenter tersebut dengan syarat 1 Presenter mewakili 1 View

public interface Presenter<T extends View> {
void onAttach(T view);

void onDetach();
}

Setelah itu, kita akan buat class implementasinya. Hal pertama yang akan kita lakukan adalah membuat interface dari layout yang kita sudah buat sebelumnya dengan nama MainView.java

public interface MainView extends View {
void onShowFragment(Data data);
}

Lalu, kita lanjut dengan membuat class dari si Presenter tersebut dengan nama MainPresenter.java

public class MainPresenter implements Presenter<MainView> {
private MainView mView;

@Override
public void onAttach(final MainView view) {
mView = view;
}

@Override
public void onDetach() {
mView = null;
}

public void showFragment() {
// Set Data
final Data data = new Data();
data.setText("Hello from Data!");

// Show Fragment with Data
mView.onShowFragment(data);
}
}

Pada code di atas, kita bisa melihat bahwa object View sudah kita invoke kedalam Presenter menggunakan fungsi dari onAttach dan onDetach. Sedangkan fungsi showFragment akan di panggil melalui class MainActivity dan ketika data dari model tersebut sudah siap maka Presenter akan meneruskan-nya melalui sebuah Contract yang sudah kita definisikan pada MainView

public class MainActivity extends AppCompatActivity implements MainView {
MainPresenter presenter;

@Override
protected void onCreate(@Nullable final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initPresenter();
onAttachView();
}

@Override
public void onAttachView() {
presenter.onAttach(this);
addButtonListener();
}

@Override
public void onDetachView() {
presenter.onDetach();
}

@Override
public void onShowFragment(final Data data) {
// Get Data
final Bundle bundle = new Bundle();
bundle.putString("data", data.getText());

// Show Fragment with Data
final String tag = ResultFragment.class.getSimpleName();
final Fragment fragment = ResultFragment.newInstance();
fragment.setArguments(bundle);

// Begin Fragment Transaction
final FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.fl_main, fragment, tag);
fragmentTransaction.commit();
}

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

private void initPresenter() {
presenter = new MainPresenter();
}

private void addButtonListener() {
final Button button = (Button) findViewById(R.id.btn_main);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View view) {
button.setVisibility(View.GONE);
presenter.showFragment();
}
});
}
}

Pada class MainActivity kita bisa melihat bahwa Contract dari MainView sudah diimplementasikan dengan nama onShowFragment dimana sebelumnya si Presenter kita panggil ketika button melakukan event click, sehingga data yang dibawa dari Presenter dapat digunakan dan di teruskan ke object lainnya (sesuai kebutuhan, dalam hal ini Saya coba meneruskan data tersebut pada sebuah Fragment)…

Apakah teman-teman sudah cukup jelas bagaimana cara kerja dari pattern MVP ini ? jika belum kamu bisa melihat source dari artikel ini pada link berikut

Selamat belajar, dan Sampai jumpa di kesempatan berikutnya :)