A、Android之MVC模式

MVC (Model-View-Controller):
  M是指逻辑模型,V是指视图模型,C则是控制器。
  一个逻辑模型可以对于多种视图模型,比如一批统计数据你可以分别用柱状图、饼图来表示。一种视图模型也可以对于多种逻辑模型。使用MVC的目的是将M和V的实现代码分离,从而使同一个程序可以使用不同的表现形式,而C存在的目的则是确保M和V的同步,一旦M改变,V应该同步更新。    

  MVC好处:从用户的角度出发,用户可以根据自己的需求,选择自己合适的浏览数据的方式。比如说,对于一篇在线文档,用户可以选择以HTML网页的方式阅读,也可以选择以pdf的方式阅读。从开发者的角度,MVC把应用程序的逻辑层与界面是完全分开的,最大的好处是:界面设计人员可以直接参与到界面开发,程序员就可以把精力放在逻辑层上。而不是像以前那样,设计人员把所有的材料交给开发人员,由开发人员来实现界面。

在Eclipes工具中开发Android采用了更加简单的方法,设计人员在DroidDraw中设计界面,以XML方式保存,在Eclipes中直接打开就可以看到设计人员设计的界面。      

  Android中界面部分也采用了当前比较流行的MVC框架,在Android中:    

 1) 视图层(View):一般采用XML文件进行界面的描述,使用的时候可以非常方便的引入。当然,如何你对Android了解的比较的多了话,就一定可以想到在Android中也可以使用JavaScript+HTML等的方式作为View层,当然这里需要进行Java和JavaScript之间的通信,幸运的是,Android提供了它们之间非常方便的通信实现。            

  2) 控制层(Controller):Android的控制层的重任通常落在了众多的Acitvity的肩上,这句话也就暗含了不要在Acitivity中写代码,要通过Activity交割Model业务逻辑层处理,这样做的另外一个原因是Android中的Acitivity的响应时间是5s,如果耗时的操作放在这里,程序就很容易被回收掉。     

  3) 模型层(Model):对数据库的操作、对网络等的操作都应该在Model里面处理,当然对业务计算等操作也是必须放在的该层的。就是应用程序中二进制的数据。                  

在Android SDK中的数据绑定,也都是采用了与MVC框架类似的方法来显示数据。在控制层上将数据按照视图模型的要求(也就是Android SDK中的Adapter)封装就可以直接在视图模型上显示了,从而实现了数据绑定。比如显示Cursor中所有数据的ListActivity,其视图层就是一个ListView,将数据封装为ListAdapter,并传递给ListView,数据就在ListView中现实。

B、 什么是MVP

MVP是模型(Model)、视图(View)、主持人(Presenter)的缩写,分别代表项目中3个不同的模块。

  模型(Model):负责处理数据的加载或者存储,比如从网络或本地数据库获取数据等;

  视图(View):负责界面数据的展示,与用户进行交互;

  主持人(Presenter):相当于协调者,是模型与视图之间的桥梁,将模型与视图分离开来

安卓的mvp结构xml文件activityfragmentpresenter 安卓mvc mvp_android

一、效果图

安卓的mvp结构xml文件activityfragmentpresenter 安卓mvc mvp_ide_02


项目结构

安卓的mvp结构xml文件activityfragmentpresenter 安卓mvc mvp_mvp_03


二、Model层,javaBean

package cn.hnshangyu.mvp.bean;

/**
 * Created by Administrator on 2016/10/19.
 *
 * Model
 */

public class User {
    public String name;
    public String pwd;
}

三、登陆监听

package cn.hnshangyu.mvp.interfaceuse;

/**
 * Created by Administrator on 2016/10/19.
 */

public interface OnLoginListener {
    void loginSucess();

    void loginFailed();
}

四、登陆接口

package cn.hnshangyu.mvp.interfaceuse;

/**
 * Created by Administrator on 2016/10/19.
 */

public interface LoginInterface {
    void login(String name,String pwd,OnLoginListener loginListener);
}

五、实现(模拟)登陆

package cn.hnshangyu.mvp.interfaceuse;

import android.os.SystemClock;
import android.text.TextUtils;

import cn.hnshangyu.mvp.bean.User;

/**
 * Created by Administrator on 2016/10/19.
 */

public class UserLogin implements LoginInterface {
    @Override
    public void login(final String name, final String pwd, final OnLoginListener loginListener) {
        //模拟登陆
        new Thread(new Runnable() {
            @Override
            public void run() {
                SystemClock.sleep(3000);
                if (TextUtils.equals("xiaoguo", name) && TextUtils.equals("123456", pwd)) {
                    User user = new User();
                    user.name = name;
                    user.pwd = pwd;
                    loginListener.loginSucess();
                } else {
                    loginListener.loginFailed();
                }
            }
        }).start();
    }
}

六、View层

package cn.hnshangyu.mvp.view;

/**
 * Created by Administrator on 2016/10/19.
 *
 * View
 */

public  interface LoginView{
    String getUserName();

    String getPassword();

    void clearUserName();

    void clearPassword();

    void showLoading();

    void hideLoading();

    void toMainActivity();

    void showFailedError();
}

七、Presenter层

package cn.hnshangyu.mvp.presenter;

import android.os.Handler;
import android.os.Message;

import cn.hnshangyu.mvp.interfaceuse.OnLoginListener;
import cn.hnshangyu.mvp.interfaceuse.UserLogin;
import cn.hnshangyu.mvp.view.LoginView;

/**
 * Created by Administrator on 2016/10/19.
 * <p>
 * Presenter
 */

public class LoginPresenter {
    private static final int LOGIN_SUCESS = 88;
    private static final int LOGIN_FAILED = 99;
    private LoginView mLoginView;
    private UserLogin mUserLogin;

    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case LOGIN_SUCESS:
                    mLoginView.toMainActivity();
                    mLoginView.hideLoading();
                    break;
                case LOGIN_FAILED:
                    mLoginView.showFailedError();
                    mLoginView.hideLoading();
                    break;
            }
        }
    };

    public LoginPresenter(LoginView loginView) {
        this.mLoginView = loginView;
        this.mUserLogin = new UserLogin();
    }

    public void login() {
        mLoginView.showLoading();
        mUserLogin.login(mLoginView.getUserName(), mLoginView.getPassword(), new OnLoginListener() {
            @Override
            public void loginSucess() {
                handler.sendEmptyMessage(LOGIN_SUCESS);
            }

            @Override
            public void loginFailed() {
                handler.sendEmptyMessage(LOGIN_FAILED);
            }
        });
    }

    public void clear() {
        mLoginView.clearUserName();
        mLoginView.clearPassword();
    }
}

八、在Activity中

package cn.hnshangyu.mvp;

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.Toast;

import butterknife.ButterKnife;
import butterknife.InjectView;
import cn.hnshangyu.mvp.presenter.LoginPresenter;
import cn.hnshangyu.mvp.view.LoginView;

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

    @InjectView(R.id.et_name)
    EditText etName;
    @InjectView(R.id.et_password)
    EditText etPassword;
    @InjectView(R.id.login)
    Button login;
    @InjectView(R.id.clear)
    Button clear;
    @InjectView(R.id.login_progress)
    ProgressBar loginProgress;
    private LoginPresenter loginPresenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);
        ButterKnife.inject(this);
        initView();
    }

    private void initView() {
        hideLoading();
        loginPresenter = new LoginPresenter(this);
        login.setOnClickListener(this);
        clear.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.login:
                loginPresenter.login();
                break;
            case R.id.clear:
                loginPresenter.clear();
                break;
        }
    }

    @Override
    public String getUserName() {
        return etName.getText().toString().trim();
    }

    @Override
    public String getPassword() {
        return etPassword.getText().toString().trim();
    }

    @Override
    public void clearUserName() {
        etName.setText("");
    }

    @Override
    public void clearPassword() {
        etPassword.setText("");
    }

    @Override
    public void showLoading() {
        loginProgress.setVisibility(View.VISIBLE);
    }

    @Override
    public void hideLoading() {
        loginProgress.setVisibility(View.GONE);
    }

    @Override
    public void toMainActivity() {
        Intent intent = new Intent(this, MainActivity.class);
        startActivity(intent);
    }

    @Override
    public void showFailedError() {
        Toast.makeText(this,"登陆失败",Toast.LENGTH_LONG).show();
    }


}