Android
एमवीपी आर्किटेक्चर
खोज…
परिचय
यह विषय विभिन्न उदाहरणों के साथ 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
implements
।ErrorResponse
; इन वर्गों को यहां शामिल नहीं किया गया है क्योंकि वे सीधे इस उदाहरण का हिस्सा नहीं हैं
एमवीपी में सरल लॉगिन उदाहरण
आवश्यक पैकेज संरचना
एक्सएमएल गतिविधि_लोगिन
<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);
}
एमवीपी
एक मॉडल-व्यू-प्रस्तोता (एमवीपी) मॉडल-व्यू-कंट्रोलर (एमवीसी) वास्तुशिल्प पैटर्न की व्युत्पत्ति है। इसका उपयोग ज्यादातर उपयोगकर्ता इंटरफेस के निर्माण के लिए किया जाता है और निम्नलिखित लाभ प्रदान करता है:
- मॉडल से दृश्य अलग हो जाते हैं। प्रस्तुतकर्ता मॉडल और दृश्य के बीच मध्यस्थ है।
- यूनिट टेस्ट बनाना आसान है।
- आम तौर पर, व्यू और प्रस्तोता के बीच एक-से-एक मानचित्रण होता है, जिसमें जटिल दृश्यों के लिए कई प्रस्तुतकर्ता का उपयोग करने की संभावना होती है।