MVC
组件的互动
将应用程序划分位三种组件,模型-视图-控制器(MVC)设计定义它们之间的相互作用
-
模型(Model):用于封装与应用程序的业务逻辑相关的数据以及对数据的处理方法。
有对数据直接访问的权力,例如,对于数据库的访问。
"Model"不依赖”View“和"Controller",也就是说,Model不关心它会如何显示或是如何被操作。但是Model中数据的变化一般会通过一种刷新机制被公布。为了实现这种机制,那些用于监视此Model的View必须事先在此Model上注册,从而,View可以了解在数据Model上面发生的改变。(观察者模式,软件设计模式)
-
视图(View):能够实现数据有目的的显示(理论上,这不是必需的)。在View中一般没有程序上的逻辑。为了实现View上的刷新功能,View需要访问 它监视的数据模型(Model),因此应该事先在被它监视的数据那里注册
-
控制器(Control):起到不同层面间的组织作用,用于控制应用程序的流程。它处理事件并作出相应。"事件"包括用户的行为和数据Model上的改变
经典操作流程:(其中一种合作方式)
user——>Controller ——>Model——>View——>user
在不同项目开发里面,分别有不同的内容充当MVC
View:Activity\fragment的视图
Controller:对应着Activity,fragment,绑定UI,处理各种事务
Model:数据的获取,储存,更新,domain
现阶段使用的是MVP模式
View(xml)<=>Controller<=>Model
V P M
优点
View与Model隔离,View换了,Model不影响。Model换其他数据源,View层也不受影响。一个View可以连接多个Model,有些Model可以复用。比如一个页面需要用户信息,另一个页面也需要用户信息。
缺点
不适合在Android开发上使用。在Android开发中,View的相关内容和Controller都写到一起了,会让Activity或Fragment越来越臃肿
下图是Android关系流程图
MVC实例
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:orientation="vertical"
tools:context=".MainActivity">
<EditText
android:id="@+id/user_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="textPersonName"
android:text="Name" />
<EditText
android:id="@+id/password"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="textPassword" />
<Button
android:id="@+id/login_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="登录" />
<TextView
android:id="@+id/login_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
UserModel.java
package com.example.mvc;
import java.util.Random;
import javax.security.auth.callback.Callback;
public class UserModel {
private API api;
Random random = new Random();
/**
* 进行登录操作*/
public void doLogin(RequestCallBack callBack,String user,String password) {
callBack.onLoading();
//开始去调用登录的API
//api.login
//有结果,此操作为耗时操作
int randomValue = random.nextInt(2);
if(randomValue == 0) {
callBack.onFailed();
} else {
callBack.onSuccess();
}
}
}
MainActivty.java
package com.example.mvc;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import javax.security.auth.callback.Callback;
public class MainActivity extends AppCompatActivity implements RequestCallBack{
private Button loginButton;
private EditText userName,password;
private TextView loginText;
private UserModel userModel = new UserModel();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setViews();
initListener();
}
private void setViews() {
loginButton = findViewById(R.id.login_button);
userName = findViewById(R.id.user_name);
password = findViewById(R.id.password);
loginText = findViewById(R.id.login_text);
}
private void initListener() {
loginButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
toLogin();
}
});
}
/**
* 登录的逻辑处理
*/
private void toLogin() {
String user = userName.getText().toString();
String passwordToString = password.getText().toString();
//检查账号格式是否正确
if(TextUtils.isEmpty(user)){
//TODO:提示账号有问题
}
//检查密码长度是否正确
if(TextUtils.isEmpty(passwordToString)){
//TODO:提示密码有问题
}
//给密码加密
//进行登录,此操作是异步
userModel.doLogin(this,user,passwordToString);
//禁止按钮可以点击,不可以点击了,防止重复提交
loginButton.setEnabled(false);
}
@Override
public void onSuccess() {
loginText.setText("登录成功");
}
@Override
public void onFailed() {
loginText.setText("登录失败");
}
@Override
public void onLoading() {
loginText.setText("登录中。。。");
}
}
RequestCallBack.java
package com.example.mvc;
public interface RequestCallBack {
void onSuccess();
void onFailed();
void onLoading();
}