معماری MVP در اندروید

آموزش معماری mvvm اندروید - آموزش معماری mvvm در اندروید - آموزش برنامه نویسی اندروید پروژه محور - آموزش پروژه محور برنامه نویسی اندروید استودیو

الگوی MVP (Model View Presenter) مشتق شده از معماری شناخته شده MVC (Model View Controller) است و یکی از محبوب ترین الگوها برای سازماندهی لایه Presenter در برنامه های Android است.

معماری MVP در اندروید چیست؟

معماری MVP اجازه می دهد تا لایه Presenter از منطق جدا شود ، به طوری که همه چیز در مورد نحوه عملکرد UI از نحوه نمایش آن بر روی صفحه نمایش جدا است. در حالت ایده آل ، الگوی MVP به این نتیجه می رسد که همان منطق ممکن است دارای دیدگاههای کاملاً متفاوت و قابل تعویض باشد.

اولین چیزی که باید روشن شود این است که MVP به خودی خود یک معماری نیست ، بلکه تنها مسئولیت لایه Presenter را بر عهده دارد. این یک ارزیابی بحث برانگیز بوده است ، بنابراین می خواهم آن را کمی عمیق تر توضیح دهم.

ممکن است متوجه شوید که MVP به عنوان یک الگوی معماری تعریف شده است زیرا می تواند بخشی از معماری برنامه شما باشد ، اما این را در نظر نگیرید که فقط به دلیل استفاده از MVP ، معماری شما کامل است. MVP فقط لایه Presenter را مدل می کند اما اگر می خواهید یک برنامه انعطاف پذیر و مقیاس پذیر داشته باشید ، بقیه لایه ها هنوز هم نیاز به یک معماری خوب دارند.

چرا از معماری MVP در اندروید استفاده می کنیم؟

در Android مشکل ما ناشی از این واقعیت است که Activity های Android با مکانیزم های دسترسی UI و مکانیزم دسترسی به داده ها نزدیک است. ما می توانیم نمونه های افراطی مانند CursorAdapter را پیدا کنیم ، که آداپتورها را که بخشی از view هستند ، ترکیب کنند با cursors ، چیزی که باید به اعماق لایه دسترسی به داده ها منتقل شود.

برای اینکه یک برنامه به راحتی قابل توسعه و نگهداری باشد ، باید لایه های کاملاً جدا از هم تعریف کنیم. فردا چه کاری انجام میدهیم اگر به جای بازیابی همان داده ها از یک پایگاه داده ، بخواهیم آن را از یک سرویس وب دریافت کنیم؟ ما مجبوریم کل view های خود را دوباره از اول بسازیم .

معماری MVP در واقع لایه view را از منبع داده های ما مستقل می کند. ما برنامه را حداقل به سه لایه مختلف تقسیم می کنیم ، که به ما امکان می دهد آنها را بطور مستقل تست کنیم. با MVP بیشتر منطق را از Activity خارج می کنیم تا بتوانیم بدون استفاده از تست های ابزار دقیق آن را آزمایش کنیم.

ایجاد یک پروژه ساده برای درک بهتر معماری MVP در اندروید :

یک پروژه جدید در اندروید استودیو ایجاد میکنیم . نام لی اوت را به activity_login تغییر میدهیم . روت لی اوت را به LinearLayout تغییر داده و درون آن 2 EditText و یک TextView به صورت زیر میگذاریم :

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:gravity="center_vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".activities.LoginActivity">

    <EditText
        android:id="@+id/etUserName"
        android:layout_marginRight="25dp"
        android:layout_marginLeft="25dp"
        android:hint="Enter UserName ..."
        android:inputType="textPersonName"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <EditText
        android:id="@+id/etPassword"
        android:layout_marginTop="25dp"
        android:layout_marginRight="25dp"
        android:layout_marginLeft="25dp"
        android:hint="Enter Password ..."
        android:inputType="textPassword"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/tvLogin"
        android:padding="12dp"
        android:textSize="22sp"
        android:textColor="#fff"
        android:textStyle="bold"
        android:background="@color/colorPrimaryDark"
        android:text="LOGIN"
        android:gravity="center"
        android:layout_marginTop="25dp"
        android:layout_marginRight="25dp"
        android:layout_marginLeft="25dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>

سه پکیج جدید با نام های model ، view و presenter در پروژه ایجاد میکنیم . یک پکیج دیگر به نام activities نیز ایجاد کرده . اکتیویتی اصلی را به LoginActivity تغییر نام داده و درون پکیج activities میگذاریم .حال باید 2 اینترفیس در پکیج های view و presenter ایجاد کنیم . ابتدا روی پکیج view راست کلیک کرده ، New و سپس Java Class را میزنیم . نوع آنرا از Class به Interface تغییر میدهیم . نام این اینترفیس را LoginView گذاشته و ok را میزنیم تا اینترفیس ایجاد شود .

سپس روی پکیج presenter راست کلیک کرده ، New و سپس Java Class را میزنیم . نوع آنرا از Class به Interface تغییر میدهیم . نام این اینترفیس را LoginPresenter گذاشته و ok را میزنیم تا اینترفیس دوم نیز ایجاد شود .

کد های اینترفیس LoginView به صورت زیر میباشد :

package com.elecomco.simplemvp.view;

public interface LoginView {
    void loginValidations();
    void loginSuccess();
    void loginError();
}

همانطور که مشاهده میکنید 3 بدنه تابع در این اینترفیس ایجاد کرده ایم تا هنگام ارث بری از اینترفیس آنها را پیاده سازی کنیم .

یک بدنه تابع با نام preFormLogin در اینترفیس LoginPresenter ایجاد کرده که شامل 2 ورودی از نوع رشته میباشد . در واقع میخواهیم یوزر نیم و پسورد در این اینترفیس گرفته شود . یا بهتر بگم ورودی ها رو از لایه Presenter دریافت میکنیم .

package com.elecomco.simplemvp.presenter;

public interface LoginPresenter {
    void preFormLogin(String userName,String password);
}

حالا یه کلاس میخوایم که از اینترفیس LoginPresenter ارث بری کنه (implements) ، و توابع اون رو پیاده سازی کنه . در پکیج model که در واقع نقش لایه مدل رو بازی میکنه ، یه کلاس جدید با نام PresenterImpl میسازیم .کد های این کلاس به صورت زیر میباشد :

package com.elecomco.simplemvp.model;

import android.text.TextUtils;

import com.elecomco.simplemvp.presenter.LoginPresenter;
import com.elecomco.simplemvp.view.LoginView;

public class PresenterImpl implements LoginPresenter {

    LoginView mLoginView;

    public PresenterImpl(LoginView mLoginView) {
        this.mLoginView = mLoginView;
    }

    @Override
    public void preFormLogin(String userName, String password) {
        if(TextUtils.isEmpty(userName) || TextUtils.isEmpty(password)){
            mLoginView.loginValidations();
        }else {
            if(userName.equals("mohammad") && password.equals("123")){
                mLoginView.loginSuccess();
            }else {
                mLoginView.loginError();
            }
        }
    }
}

همانطور که مشاهده میکنید ورودی Constractor ما همان اینترفیسی هست که در لایه ویو ایجاد کرده ایم . یوزر نیم و پسورد را چک میکنیم . اگر مقدار آنها خالی بود تابع loginValidations فراخوانی میشود . اگر مقدار آنها برابر مقادیر دلخواه خودم بود تابع loginSuccess و اگر مقادیر وارد شده اشنباه بود ، تابع loginError فراخوانی میشود .

در اینجا کاملا اختیار از view گرفته شده است و اصلا نمیداند از کجا گرفته میشوند و به چه شکلی پیاده سازی میشوند . لایه مدل اطلاعات را از لایه Presenter دریافت میکند و view فقط یک شکل نمایشی دارد و دستورات اصلی را لایه Presenter ایجاد میکند و لایه View فقط اطاعت میکند .

حالا میرسیم به کدنویسی اکتیویتی :

package com.elecomco.simplemvp.activities;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import com.elecomco.simplemvp.R;
import com.elecomco.simplemvp.model.PresenterImpl;
import com.elecomco.simplemvp.presenter.LoginPresenter;
import com.elecomco.simplemvp.view.LoginView;

public class LoginActivity extends AppCompatActivity implements View.OnClickListener, LoginView {

    EditText etUserName,etPassword;
    TextView tvLogin;

    LoginPresenter mLoginPresenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);

        etUserName=findViewById(R.id.etUserName);
        etPassword=findViewById(R.id.etPassword);

        tvLogin=findViewById(R.id.tvLogin);
        tvLogin.setOnClickListener(this);

        mLoginPresenter=new PresenterImpl(LoginActivity.this);

    }

    @Override
    public void onClick(View v) {
        String userName=etUserName.getText().toString();
        String password=etPassword.getText().toString();

        mLoginPresenter.preFormLogin(userName,password);

    }

    @Override
    public void loginValidations() {
        Toast.makeText(this, "Please Enter username and password!", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void loginSuccess() {
        Toast.makeText(this, "Login Success!", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void loginError() {
        Toast.makeText(this, "Login Failure!", Toast.LENGTH_SHORT).show();
    }
}

این ساده ترین پروژه ای بود که برای مفهوم معماری MVP در اندروید ایجاد کردیم . همینطور که میبینید محتوای ادیت تکست ها دیگه در لی اوت چک نمیشن ، لی اوت ما دیگه اینجا هیچ کاره هست و فقط حالت نمایشی داره . کارهای اصلی رو لایه Presenter داره انجام میده . حالا اگه بخواین اکتیویتی رو به فرگمنت تبدیل کنید ، خیلی راحت و بدون اینکه در برنامتون تغییری ایجاد بشه ، این کار رو انجام میدین .

تو پروژه های بزرگ میتونید با معماری MVP آپدیت هاتون رو به راحتی و در کمترین زمان انجام بدین و نیاز نیست کل برنامتون رو از اول بنویسید . فرض کنید اینستاگرام بخواد یه آپشن جدید به اپلیکیشنش اضاف کنه ، اگر از ابتدا معماریش درست پیاده سازی نشه ، مجبوره خیلی از قسمتای برنامه نویسی رو پاک کنه و از اول به یه شکل دیگه بنویسه .

امروزه شرکت های بزرگ برای اسخدام برنامه نویس اندروید یکی از شرط هاشون تسلط برنامه نویس به معماری MVP هست . ما در دوره آموزش برنامه نویسی اندروید یه اپلیکیشن خبری رو با استفاده از این معماری پیاده سازی کردیم . امیدوارم که این آموزش براتون مفید و سودمند باشه . پیروز و سربلند باشید . /p>

سوالات و نظرات خود را در این بخش مطرح کنید

avatar
فهرست