Android代码架构之MVP

1、引言

9月到了,不知道同学们的暑假作业有没有抄完,想到学校已经离我远去,还真的有点伤感呢,不过没关系,即使离开了学校咱还是可以继续学习是不是,好吧,让我们来开始今天的学习MVP架构

2、为什么要学习MVP架构?

相信很多同学之前都跟我这个菜鸡一样,写代码的时候都是想到哪儿写到哪儿,从左到右,从上到下,写完之后运行一下,没有Bug继续往下写,这样做似乎一直也没出什么问题
但是,我们发现这样做的结果就是我们的某个类中往往写了大量的代码和逻辑,一个项目中行数过千的类估计也不在少数,在写了一段时间后别人很难看懂我们的思路,有时甚至是我们自己也会被这上千行的代码搞得头皮发麻,其实,将所有逻辑都写在一个类中这首先就不符合我们的软件设计原则中的单一职责原则,那么怎么样才能使我们的代码变得更优雅,每一个类都各司其职呢?答案就是本片文章的主角——MVP架构

3、MVP架构的概念

要理解MVP的概念我们需要分别理解这M,V,P在我们的项目中分别负责做哪些事,他们在项目中具体对应哪些类?

首先说M,M是Model的缩写,是模型的意思,他在我们的项目中通常负责一些数据的获取与操作,在项目中具体对应那些实体模型类和一些写网络或本地数据获取逻辑的类;V是View的缩写,,通常负责界面的展示和人机交互的逻辑编写,在项目中具体表现为XML布局,自定义的布局类,Activity和Fragment等,P是Presenter的缩写,字面意思是主持人,其实他就是M和View的交互中间人,我们之前写代码的时候之所以会出现将所有逻辑和代码都写在一个类中的情况其实就是因为我们没有将逻辑代码和视图操作代码分离,导致我们的activity,fragment中既有他们自己该做的视图相关的工作还有本来不应该属于他们的逻辑代码操作,如我们能通过Presenter这个中间人将所有的逻辑代码都写到Model中,使我们的视图层只做他们该做的事岂不美哉!不知道上面说了一大通诸位理解了没有,为了方便大家理解,去网上盗波图先
从上图中我们发现,View和Model互不干涉,各司其职,如果他们想发生关系必须通过Presenter这个中间人来处理,光说不练假把式,说得再多,不会敲还是没用,下面我将会通过一个注册的Demo来给大家演示MVP的写法

4、代码演示

首先可以先给大家看一下没有采用MVP架构时注册的写法

package com.example.machenike.netdemo10;

import android.app.ProgressDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

public class RegisterActivity extends AppCompatActivity {

    private EditText mUsername;
    private EditText mPassword;
    private String mUsername1;
    private String mPassword1;
    private ProgressDialog mProgressDialog;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_register);
        mUsername = (EditText) findViewById(R.id.username);
        mPassword = (EditText) findViewById(R.id.password);
    }

    public void register(View view) {
        mUsername1 = mUsername.getText().toString().trim();
        mPassword1 = mPassword.getText().toString().trim();

        User user = new User();
        user.setUserName(mUsername1);
        user.setPassword(mPassword1);
        mProgressDialog = ProgressDialog.show(this, "注册", "玩命儿注册中.....");
        RetrofitClient.getInstance().getAPI().postRequest(user).enqueue(new Callback<UserResult>() {


            @Override
            public void onResponse(Call<UserResult> call, Response<UserResult> response) {
                mProgressDialog.dismiss();
                if (response.isSuccessful()){
                    UserResult userResult = response.body();
                    if (userResult!=null){
                        if (userResult.getErrcode()==1){
                            Toast.makeText(RegisterActivity.this,"注册成功!!",Toast.LENGTH_SHORT).show();
                            return;
                        }
                        Toast.makeText(RegisterActivity.this,userResult.getErrmsg(),Toast.LENGTH_SHORT).show();
                        return;
                    }
                    Toast.makeText(RegisterActivity.this,"未知错误!",Toast.LENGTH_SHORT).show();
                }
            }

            @Override
            public void onFailure(Call<UserResult> call, Throwable t) {
                mProgressDialog.dismiss();
                Toast.makeText(RegisterActivity.this,"注册失败",Toast.LENGTH_SHORT).show();
            }
        });

    }
}
从上面的代码中我们可以看出弹吐司,进度条,网络请求等一系列代码全部挤在了RegisterActivity这个类中,有些同学可能会说了,这不是看着挺好的么。是,是挺好的,可这只是一个Demo如果在真实的开发环境下,你的Activity中都只会是这点代码么?所以我们需要将里面的代码进行拆分,我们可以将里面的逻辑分为两大类,一个是与视图相关的,一个是与视图无关的,由于Activity本身就属于视图层,所以很显然,与视图相关的代码我们可以保留,与视图无关的拆分到Model中,在这里哪些与视图相关呢,哪些与视图无关呢?很显然,弹吐司,进度条这些与视图有关,网络请求与视图无关,所以我们要拆分出去的代码主要就是这一段
下面我将会贴出采用MVP的注册的写法,让大家理解拆分的过程
 
 
首先给大家看一下我的项目结构
在这个工程中我建了m,v,p,net四个包,在m中还有个entity放置实体类的二级包,net包中是我封装的网络请求客户端,这里不做重点讨论,m,v,p这个三个包中分别放置MVP对应的文件,我们会发现,基本上每个类都一个接口与之对应,这里也是借鉴了一些面向接口编程的思想,看完了项目结构,给大家看一下Model中我们是怎么写的
首先看接口
接着看他的实现类
package com.example.machenike.mvpdemo.m;

import android.util.Log;

import com.example.machenike.mvpdemo.m.entity.User;
import com.example.machenike.mvpdemo.m.entity.UserResult;
import com.example.machenike.mvpdemo.net.RetrofitClient;
import com.example.machenike.mvpdemo.p.RegisterPresenter;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

/**
 * Created by MACHENIKE on 2017/9/1.
 */

public class RegisterModeImpl implements RegisterModel{
    private RegisterPresenter mRegisterPresenter;

    public RegisterModeImpl(RegisterPresenter registerPresenter) {
        mRegisterPresenter = registerPresenter;
    }

    @Override
    public void register(User user) {
        Log.e("============","RegisterModeImpl");
        //显示进度条
        mRegisterPresenter.showProgress();
        RetrofitClient.getInstance().getAPI().register(user).enqueue(new Callback<UserResult>() {
            @Override
            public void onResponse(Call<UserResult> call, Response<UserResult> response) {
                //隐藏进度条
                mRegisterPresenter.hideProgress();
                if (response.isSuccessful()){
                    UserResult userResult = response.body();
                    if (userResult==null){
                        //展示错误信息
                        mRegisterPresenter.showMessage("未知错误");
                        return;
                    }
                    if (userResult.getErrcode()!=1){
                        //展示错误信息
                        mRegisterPresenter.showMessage(userResult.getErrmsg());
                        return;
                    }

                    //注册成功
                    mRegisterPresenter.showMessage("注册成功!");
                }
            }

            @Override
            public void onFailure(Call<UserResult> call, Throwable t) {
                //隐藏进度条
                mRegisterPresenter.hideProgress();
                //展示错误信息
                mRegisterPresenter.showMessage("注册失败");
            }
        });
    }
}
我们发现Model的实现类完成了我们刚才写在Activity中的网络请求,我们还发现Model的构造方法中传入了一个Presenter的对象,是的,Presenter作为桥梁,如果我们的Model中不持有其对象我们该怎样将数据传输给View呢
 
 
接着,我们来看一下Presenter的代码,首先是接口
然后是实现类
我们发现Presenter的构造方法中传入了一个Activity也就是View的对象,除此之外,在Presenter的构造中还创建了一个Model的对象,并将自己的对象穿给了Model,除了构造方法外,Presenter中还有四个方法,其中三个与View相关一个与Model相关,是的,作为中间人要不偏不倚,雨露均沾,我们在getDataFromModel中调用register方法,在其他三个方法中调用View相关的另外三个方法
 
最后只剩下Activity也就是View的代码了,同样先看接口
接着实现类
在这里我们发现,Activity中只有与视图相关的代码,当我们想要获取数据的时候只要呼叫一声中间人
new RegisterPresenterImpl(this).getDataFromModel(new User(userName,passWord));
中间人就会去Model中拿到数据并返回
 
 
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值