खोज…


परिचय

यह विषय विभिन्न उदाहरणों के साथ Android के मॉडल ‑ व्यू will प्रस्तुतकर्ता (एमवीपी) वास्तुकला प्रदान करेगा।

टिप्पणियों

एंड्रॉइड ऐप को आर्किटेक्ट करने के कई तरीके हैं। लेकिन उनमें से सभी परीक्षण योग्य नहीं हैं और हमें अपने कोड की संरचना करने की अनुमति देता है ताकि ऐप को परीक्षण करना आसान हो। एक परीक्षण योग्य वास्तुकला का मुख्य विचार आवेदन के कुछ हिस्सों को अलग कर रहा है जो उन्हें बनाए रखने, विस्तार करने और एक दूसरे से अलग परीक्षण करने में आसान बनाता है।

एमवीपी परिभाषा

नमूना

एक अच्छी स्तरित वास्तुकला के साथ एक आवेदन में, यह मॉडल केवल डोमेन परत या व्यावसायिक तर्क का प्रवेश द्वार होगा। इसे उस डेटा के प्रदाता के रूप में देखें जिसे हम दृश्य में प्रदर्शित करना चाहते हैं।

राय

आमतौर पर Activity या Fragment द्वारा लागू किया गया दृश्य, प्रस्तुतकर्ता के लिए एक संदर्भ होगा। केवल एक चीज जो दृश्य करेगी वह है कि हर बार प्रस्तुतकर्ता से एक विधि को कॉल करने के लिए एक इंटरफ़ेस कार्रवाई होती है।

प्रस्तुतकर्ता

प्रस्तुतकर्ता दृश्य और मॉडल के बीच मध्य व्यक्ति के रूप में कार्य करने के लिए जिम्मेदार है। यह मॉडल से डेटा पुनर्प्राप्त करता है और इसे व्यू में स्वरूपित करता है। लेकिन विशिष्ट एमवीसी के विपरीत, यह भी तय करता है कि जब आप दृश्य के साथ बातचीत करते हैं तो क्या होता है।

* एंटोनियो लीवा के लेख से परिभाषाएँ

अनुशंसित ऐप संरचना (आवश्यक नहीं)

ऐप को प्रति फीचर पैकेज द्वारा संरचित किया जाना चाहिए। यह पठनीयता में सुधार करता है और ऐप को इस तरह से संशोधित करता है कि इसके हिस्सों को एक-दूसरे से स्वतंत्र रूप से बदला जा सके। ऐप की प्रत्येक मुख्य विशेषता अपने स्वयं के जावा पैकेज में है।

मॉडल दृश्य प्रस्तुतकर्ता (MVP) पैटर्न में लॉगिन उदाहरण

आइए एक साधारण लॉगिन स्क्रीन का उपयोग करके एमवीपी को देखें। दो Button हैं- एक लॉगिन एक्शन के लिए और दूसरा पंजीकरण स्क्रीन के लिए; दो EditText एक ईमेल के लिए और दूसरा पासवर्ड के लिए।

LoginFragment (देखें)

public class LoginFragment extends Fragment implements LoginContract.PresenterToView, View.OnClickListener {

    private View view;
    private EditText email, password;
    private Button login, register;

    private LoginContract.ToPresenter presenter;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_login, container, false);
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        email = (EditText) view.findViewById(R.id.email_et);
        password = (EditText) view.findViewById(R.id.password_et);
        login = (Button) view.findViewById(R.id.login_btn);
        login.setOnClickListener(this);
        register = (Button) view.findViewById(R.id.register_btn);
        register.setOnClickListener(this);

        presenter = new LoginPresenter(this);

        presenter.isLoggedIn();

    }

    @Override
    public void onLoginResponse(boolean isLoginSuccess) {
        if (isLoginSuccess) {
            startActivity(new Intent(getActivity(), MapActivity.class));
            getActivity().finish();
        }
    }

    @Override
    public void onError(String message) {
        Toast.makeText(getActivity(), message, Toast.LENGTH_SHORT).show();
    }

    @Override
    public void isLoggedIn(boolean isLoggedIn) {
        if (isLoggedIn) {
            startActivity(new Intent(getActivity(), MapActivity.class));
            getActivity().finish();
        }
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.login_btn:
                LoginItem loginItem = new LoginItem();
                loginItem.setPassword(password.getText().toString().trim());
                loginItem.setEmail(email.getText().toString().trim());
                presenter.login(loginItem);
                break;
            case R.id.register_btn:
                startActivity(new Intent(getActivity(), RegisterActivity.class));
                getActivity().finish();
                break;
        }
    }
}

LoginPresenter (प्रस्तुतकर्ता)

public class LoginPresenter implements LoginContract.ToPresenter {

    private LoginContract.PresenterToModel model;
    private LoginContract.PresenterToView view;

    public LoginPresenter(LoginContract.PresenterToView view) {
        this.view = view;
        model = new LoginModel(this);
    }

    @Override
    public void login(LoginItem userCredentials) {
        model.login(userCredentials);
    }

    @Override
    public void isLoggedIn() {
        model.isLoggedIn();
    }

    @Override
    public void onLoginResponse(boolean isLoginSuccess) {
        view.onLoginResponse(isLoginSuccess);
    }

    @Override
    public void onError(String message) {
        view.onError(message);
    }

    @Override
    public void isloggedIn(boolean isLoggedin) {
        view.isLoggedIn(isLoggedin);
    }
}

LoginModel (मॉडल)

public class LoginModel implements LoginContract.PresenterToModel, ResponseErrorListener.ErrorListener {

    private static final String TAG = LoginModel.class.getSimpleName();
    private LoginContract.ToPresenter presenter;

    public LoginModel(LoginContract.ToPresenter presenter) {
        this.presenter = presenter;
    }

    @Override
    public void login(LoginItem userCredentials) {
        if (validateData(userCredentials)) {
            try {
                performLoginOperation(userCredentials);
            } catch (JSONException e) {
                e.printStackTrace();
            }
        } else {
            presenter.onError(BaseContext.getContext().getString(R.string.error_login_field_validation));
        }
    }

    @Override
    public void isLoggedIn() {
        DatabaseHelper database = new DatabaseHelper(BaseContext.getContext());
        presenter.isloggedIn(database.isLoggedIn());
    }

    private boolean validateData(LoginItem userCredentials) {
        return Patterns.EMAIL_ADDRESS.matcher(userCredentials.getEmail()).matches()
                && !userCredentials.getPassword().trim().equals("");
    }

    private void performLoginOperation(final LoginItem userCredentials) throws JSONException {

        JSONObject postData = new JSONObject();
        postData.put(Constants.EMAIL, userCredentials.getEmail());
        postData.put(Constants.PASSWORD, userCredentials.getPassword());

        JsonObjectRequest request = new JsonObjectRequest(Request.Method.POST, Url.AUTH, postData,
                new Response.Listener<JSONObject>() {
                    @Override
                    public void onResponse(JSONObject response) {
                        try {
                            String token = response.getString(Constants.ACCESS_TOKEN);
                            DatabaseHelper databaseHelper = new DatabaseHelper(BaseContext.getContext());
                            databaseHelper.login(token);
                            Log.d(TAG, "onResponse: " + token);
                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                        presenter.onLoginResponse(true);
                    }
                }, new ErrorResponse(this));

        RequestQueue queue = Volley.newRequestQueue(BaseContext.getContext());
        queue.add(request);
    }

    @Override
    public void onError(String message) {
        presenter.onError(message);
    }
}

कक्षा आरेख

कक्षा आरेख के रूप में कार्रवाई देखें। यहाँ छवि विवरण दर्ज करें

टिप्पणियाँ:

  • यह उदाहरण नेटवर्क संचार के लिए वॉली का उपयोग करता है, लेकिन एमवीपी के लिए इस पुस्तकालय की आवश्यकता नहीं है
  • UrlUtils एक ऐसा वर्ग है जिसमें मेरे API समापन बिंदु के सभी लिंक हैं
  • ResponseErrorListener.ErrorListener एक interface जो ErrorResponse में त्रुटि के लिए सुनता है जो वॉली के Response.ErrorListener implementsErrorResponse ; इन वर्गों को यहां शामिल नहीं किया गया है क्योंकि वे सीधे इस उदाहरण का हिस्सा नहीं हैं

एमवीपी में सरल लॉगिन उदाहरण

आवश्यक पैकेज संरचना

आवश्यक पैकेज संरचना

एक्सएमएल गतिविधि_लोगिन

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_vertical"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin">

    <EditText
        android:id="@+id/et_login_username"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="USERNAME" />

    <EditText
        android:id="@+id/et_login_password"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="PASSWORD" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <Button
            android:id="@+id/btn_login_login"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginRight="4dp"
            android:layout_weight="1"
            android:text="Login" />

        <Button
            android:id="@+id/btn_login_clear"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="4dp"
            android:layout_weight="1"
            android:text="Clear" />
    </LinearLayout>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="3dp"
        android:text="correct user: mvp, mvp" />

    <ProgressBar
        android:id="@+id/progress_login"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="40dp" />

</LinearLayout>

गतिविधि कक्षा LoginActivity.class

public class LoginActivity extends AppCompatActivity implements ILoginView, View.OnClickListener {
    private EditText editUser;
    private EditText editPass;
    private Button   btnLogin;
    private Button   btnClear;
    private ILoginPresenter loginPresenter;
    private ProgressBar progressBar;

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

        //find view
        editUser = (EditText) this.findViewById(R.id.et_login_username);
        editPass = (EditText) this.findViewById(R.id.et_login_password);
        btnLogin = (Button) this.findViewById(R.id.btn_login_login);
        btnClear = (Button) this.findViewById(R.id.btn_login_clear);
        progressBar = (ProgressBar) this.findViewById(R.id.progress_login);

        //set listener
        btnLogin.setOnClickListener(this);
        btnClear.setOnClickListener(this);

        //init
        loginPresenter = new LoginPresenterCompl(this);
        loginPresenter.setProgressBarVisiblity(View.INVISIBLE);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btn_login_clear:
                loginPresenter.clear();
                break;
            case R.id.btn_login_login:
                loginPresenter.setProgressBarVisiblity(View.VISIBLE);
                btnLogin.setEnabled(false);
                btnClear.setEnabled(false);
                loginPresenter.doLogin(editUser.getText().toString(), editPass.getText().toString());
                break;
        }
    }

    @Override
    public void onClearText() {
        editUser.setText("");
        editPass.setText("");
    }

    @Override
    public void onLoginResult(Boolean result, int code) {
        loginPresenter.setProgressBarVisiblity(View.INVISIBLE);
        btnLogin.setEnabled(true);
        btnClear.setEnabled(true);
        if (result){
            Toast.makeText(this,"Login Success",Toast.LENGTH_SHORT).show();
        }
        else
            Toast.makeText(this,"Login Fail, code = " + code,Toast.LENGTH_SHORT).show();
    }

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

    @Override
    public void onSetProgressBarVisibility(int visibility) {
        progressBar.setVisibility(visibility);
    }
}

ILoginView इंटरफ़ेस बनाना

प्रस्तुतकर्ता फ़ोल्डर के तहत अद्यतन जानकारी के लिए एक ILoginView इंटरफ़ेस बनाएँ निम्नानुसार है:

public interface ILoginView {
    public void onClearText();
    public void onLoginResult(Boolean result, int code);
    public void onSetProgressBarVisibility(int visibility);
}

एक ILoginPresenter इंटरफ़ेस बनाना

LoginActivity (दृश्य) के साथ संवाद करने और लॉगिन कार्यक्षमता को संभालने और गतिविधि को वापस रिपोर्ट करने के लिए LoginPresenterCompl वर्ग बनाने के लिए एक ILoginPresenter इंटरफ़ेस बनाएँ। LoginPresenterCompl वर्ग ILoginPresenter इंटरफ़ेस लागू करता है:

ILoginPresenter.class

public interface ILoginPresenter {
    void clear();
    void doLogin(String name, String passwd);
    void setProgressBarVisiblity(int visiblity);
}

LoginPresenterCompl.class

public class LoginPresenterCompl implements ILoginPresenter {
    ILoginView iLoginView;
    IUser user;
    Handler handler;

    public LoginPresenterCompl(ILoginView iLoginView) {
        this.iLoginView = iLoginView;
        initUser();
        handler = new Handler(Looper.getMainLooper());
    }

    @Override
    public void clear() {
        iLoginView.onClearText();
    }

    @Override
    public void doLogin(String name, String passwd) {
        Boolean isLoginSuccess = true;
        final int code = user.checkUserValidity(name,passwd);
        if (code!=0) isLoginSuccess = false;
        final Boolean result = isLoginSuccess;
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                    iLoginView.onLoginResult(result, code);
            }
        }, 5000);
    }

    @Override
    public void setProgressBarVisiblity(int visiblity){
        iLoginView.onSetProgressBarVisibility(visiblity);
    }

    private void initUser(){
        user = new UserModel("mvp","mvp");
    }
}

UserModel बनाना

एक UserModel बनाएँ जो LoginActivity लिए LoginActivity क्लास की तरह है। IUser सत्यापन के लिए एक IUser इंटरफ़ेस बनाएँ:

UserModel.class

public class UserModel implements IUser {
String name;
String passwd;

public UserModel(String name, String passwd) {
    this.name = name;
    this.passwd = passwd;
}

@Override
public String getName() {
    return name;
}

@Override
public String getPasswd() {
    return passwd;
}

@Override
public int checkUserValidity(String name, String passwd){
    if (name==null||passwd==null||!name.equals(getName())||!passwd.equals(getPasswd())){
        return -1;
    }
    return 0;
}

IUser.class

public interface IUser {
    String getName();

    String getPasswd();

    int checkUserValidity(String name, String passwd);
}

एमवीपी

एक मॉडल-व्यू-प्रस्तोता (एमवीपी) मॉडल-व्यू-कंट्रोलर (एमवीसी) वास्तुशिल्प पैटर्न की व्युत्पत्ति है। इसका उपयोग ज्यादातर उपयोगकर्ता इंटरफेस के निर्माण के लिए किया जाता है और निम्नलिखित लाभ प्रदान करता है:

  • मॉडल से दृश्य अलग हो जाते हैं। प्रस्तुतकर्ता मॉडल और दृश्य के बीच मध्यस्थ है।
  • यूनिट टेस्ट बनाना आसान है।
  • आम तौर पर, व्यू और प्रस्तोता के बीच एक-से-एक मानचित्रण होता है, जिसमें जटिल दृश्यों के लिए कई प्रस्तुतकर्ता का उपयोग करने की संभावना होती है।

एक मॉडल-दृश्य-प्रस्तुतकर्ता का स्केच



Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow