一、 什么是MVC
MVC全名是Model View Controller,是模型(model)-視圖(view)-控制器(controller)的縮寫谦屑,一種軟件設計典范。
- 模型(Model)—— 是應用程序中用于處理應用程序數據邏輯的部分篇梭。通常模型對象負責在數據庫中存取數據
- 視圖(View)—— 是應用程序中處理數據顯示的部分氢橙。通常視圖是依據模型數據創(chuàng)建的。
- 控制器(Controller)—— 是應用程序中處理用戶交互的部分恬偷。通澈肥郑控制器負責從視圖讀取數據,控制用戶輸入袍患,并向模型發(fā)送數據坦康。
如圖:
二、 Android中的MVC
模型層(Model):負責數據處理相關的邏輯诡延,通知View改變滞欠,會常涉及到網絡請求及Android中的datebase、SharePreference等
視圖層(View):自定義View或ViewGroup肆良,負責將用戶的請求通知Controller筛璧,并根據model更新界面
控制層(Controller):接收用戶請求并更新model
代碼案例:Login MVC
- Model
/** 模型層 ——— 登錄接口 **/
public interface ILoginModel {
void login(String username, String password, LoginCallBack callBack);
}
/** 模型層 ——— 完成具體的數據操作。 **/
public class LoginModel implements ILoginModel {
@Override
public void login(String username, String password, LoginCallBack callBack) {
if (username.equals("MVC") && password.equals("MVC")){
callBack.onLoginSuccess();
}else{
callBack.onLoginFail();
}
}
}
- View
/** 視圖層 ——— 視圖操作接口 **/
public interface ILoginView {
String getUsername();
String getPassword();
void initView();
void setViewClickListener(View.OnClickListener onclikLister);
void onUsernameEmpty(); // 用戶名為空時的顯示操作
void onPasswordEmpty(); // 密碼為空時的顯示操作
void onLoginSuccess(); // 登陸成功時的顯示操作
void onLoginFail(); // 密碼失敗時的顯示操作
}
/** 視圖層 ——— 只是作為接受用戶數據和展示數據的方式 **/
public class LoginView extends LinearLayout implements ILoginView{
private Context context;
private EditText mUsername;
private EditText mPassword;
private Button mLoginBtn;
public LoginView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
}
@Override
public void initView(){
mUsername = (EditText) findViewById(R.id.et_username);
mPassword = (EditText) findViewById(R.id.et_password);
mLoginBtn = (Button) findViewById(R.id.btn_login);
}
@Override
public String getUsername(){
return mUsername.getText().toString();
}
@Override
public String getPassword(){
return mPassword.getText().toString();
}
@Override
public void setViewClickListener(OnClickListener onclikLister){
mLoginBtn.setOnClickListener(onclikLister);
}
@Override
public void onUsernameEmpty() {
Toast.makeText(context, "用戶名不能為空", Toast.LENGTH_SHORT).show();
}
@Override
public void onPasswordEmpty() {
Toast.makeText(context, "密碼不能為空", Toast.LENGTH_SHORT).show();
}
@Override
public void onLoginSuccess() {
Toast.makeText(context, "登錄成功", Toast.LENGTH_SHORT).show();
}
@Override
public void onLoginFail() {
Toast.makeText(context, "登錄失敗", Toast.LENGTH_SHORT).show();
}
}
- Controller
public class LoginController implements View.OnClickListener {
private ILoginView loginView;
private ILoginModel loginModel;
public LoginController(ILoginView loginView){
this.loginView = loginView;
loginModel = new LoginModel();
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btn_login:
String username = loginView.getUsername();
String password = loginView.getPassword();
if (TextUtils.isEmpty(username)){
loginView.onUsernameEmpty();
}else if (TextUtils.isEmpty(password)){
loginView.onPasswordEmpty();
}
// 調用模型層去處理具體的請求
loginModel.login(username, password, new LoginCallBack() {
@Override
public void onLoginSuccess() {
// 模型層完成數據處理后,通知視圖層做出相應的改變,用戶得到反饋
loginView.onLoginSuccess();
}
@Override
public void onLoginFail() {
loginView.onLoginFail();
}
});
break;
}
}
}
- else
/** 此時Activity就變?yōu)榱顺休d視圖層的容器惹恃。 **/
public class MainActivity extends AppCompatActivity {
private LoginController controller;
private LoginView loginview;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initController();
}
private void initController(){
loginview = (LoginView) findViewById(R.id.loginview);
loginview.initView();
controller = new LoginController(loginview);
loginview.setViewClickListener(controller);
}
}
<!-- 將LoginView作為父容器 -->
<com.scnu.zhou.mvc.view.LoginView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:orientation="vertical"
android:id="@+id/loginview">
<EditText
android:id="@+id/et_username"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="text"/>
<EditText
android:id="@+id/et_password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:inputType="textPassword"/>
<Button
android:id="@+id/btn_login"
android:layout_width="match_parent"
android:layout_height="50dp"
android:text="Login"
android:layout_marginTop="10dp"/>
</com.scnu.zhou.mvc.view.LoginView>
三夭谤、 MVC模式的優(yōu)缺點
優(yōu)點:
- 耦合性低 —— 視圖層和業(yè)務層分離,這樣就允許更改視圖層代碼而不用重新編譯模型和控制器代碼
- 重用性高 —— 多個視圖能共享一個模型
- 生命周期成本低 —— MVC使開發(fā)和維護用戶接口的技術含量降低座舍。
缺點:
- 增加了系統(tǒng)結構和實現的復雜性 —— 對于簡單的界面沮翔,嚴格遵循MVC陨帆,使模型曲秉、視圖與控制器分離采蚀,會增加結構的復雜性,并可能產生過多的更新操作承二,降低運行效率榆鼠。
- 視圖與控制器間的連接過于緊密 —— 視圖與控制器是相互分離,但卻是聯(lián)系緊密的部件亥鸠,視圖沒有控制器的存在妆够,其應用是很有限的,反之亦然负蚊,這樣就妨礙了他們的獨立重用神妹。
- 視圖對模型數據的低效率訪問 —— 依據模型操作接口的不同,視圖可能需要多次調用才能獲得足夠的顯示數據家妆。對未變化數據的不必要的頻繁訪問鸵荠,也將損害操作性能。