MVP+Dragger2+Rxjava2+Retrofit+OKhttp框架已经流行很长时间,而且也必将成为未来android开发的趋势,在使用这个框架的过程中踩过很多坑,
所以想把我的经验告诉大家,让大家少踩一点弯路。
首先介绍一下MVC和MVP的概念,不懂的同学可以自行百度: 
MVC: 
  • View:对应于布局文件
  • Model:业务逻辑和实体模型
  • Controllor:对应于Activity
MVP :
  • View 对应于Activity,负责View的绘制以及与用户交互
  • Model 依然是业务逻辑和实体模型
  • Presenter 负责完成View于Model间的交互

MVC与MVP的区别:

    最明显的区别就是,MVC中是允许Model和View进行交互的,而MVP中很明显,Model与View之间的交互由Presenter完成。
    还有一点就是Presenter与View之间的交互是通过接口的(代码中会体现), 也就是说MVP中完成了M层和V层的解耦。
以上参考: http://blog.csdn.net/lmj623565791/article/details/46596109
回到本文来,我将介绍怎么把MVP引入到我们的项目中去,
在Android Studio中引入相关配置 在app的build.gradle中添加如下配置:
引入Dragger2
android {compileSdkVersion 25
    buildToolsVersion "25.0.0"
    defaultConfig {applicationId "vko.cn.myapplication"
        minSdkVersion 19
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        jackOptions {enabled true
        }
//        ndk {
//            // 设置支持的SO库架构
//            abiFilters 'armeabi' //, 'x86', 'armeabi-v7a', 'x86_64', 'arm64-v8a'
//        }
    }buildTypes {release {minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }}//使用DataBinding
    dataBinding {enabled = true
    }// 使用Java1.8, lamdba
    compileOptions {sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}
dependencies {compile fileTree(include: ['*.jar'], dir: 'libs')androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {exclude group: 'com.android.support', module: 'support-annotations'
    })compile 'com.android.support:appcompat-v7:26.+'
    compile 'com.android.support.constraint:constraint-layout:1.0.2'
    testCompile 'junit:junit:4.12'
    // Rxjava2 + Retrofit + okHttp
    compile 'io.reactivex.rxjava2:rxjava:2.1.1'
    compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
    compile 'com.squareup.retrofit2:retrofit:2.3.0'
    compile 'com.squareup.retrofit2:converter-gson:2.3.0'
    compile 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
    compile 'com.squareup.okhttp3:okhttp:3.8.1'
    //Dragger2
    compile 'com.google.dagger:dagger:2.7'
    annotationProcessor 'com.google.dagger:dagger-compiler:2.7'
    provided 'javax.annotation:jsr250-api:1.0'
    //底部菜单
    compile 'com.ashokvarma.android:bottom-navigation-bar:1.3.0'
    compile 'com.android.support:design:24.0.0'
在Module的build.gradle中引入: 
buildscript {repositories {jcenter()}dependencies {classpath 'com.android.tools.build:gradle:2.3.0'
//        //Dagger2
//        classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
        //lamdba
        classpath 'me.tatarka:gradle-retrolambda:3.2.0'
//        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.0.1-2"
//        classpath "org.jetbrains.kotlin:kotlin-android-extensions:1.0.1-2"
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}
然后开始构建项目。 项目结构如下: 

本文只是一个简单的登陆功能展示。 首先,我们来看一下M层,V层,P层的接口:如下
/**
 * Created by A on 2017/9/4.
 */

public class InterfaceContract {public interface LoginView extends BaseView {String getUserName();
        String getPassWord();
        void loginSuccess();
        void loginFail();
    }public interface Presenter<T extends BaseActivity> {void attachView(T t);

        void detachView();
    }public  interface ILoginModule{void login(String userName , String passWord, InterfaceContract.OnLoginListener listener);
    }/**
     * presenter层 的回调
     */
    public interface OnLoginListener {void LoginSucess();
        void LoginFail();
    }
}
LoginView 用来获取用户账号,密码,登陆成功,失败的相关操作 , 继承自BaseView 然后我们再来看看BaseView:
/**
 * Created by A on 2017/9/4.
 */

public interface BaseView {void startProgress();
    void stopProgress();
}
这是一个公共的显示进度的接口,用来显示,隐藏进度条,本项目的进度条采用自定义,可以再Uti包l中查看,
P层中OnLoginListener接口,是用来处理M层登陆成功,失败的回调,而Persenter接口是所有P层的公共接口,
用来处理正在网络请求时,Activity异常退出的问题。
接口看完了,让我们回到代码中,一起看看BaseAcitiviyt的代码:
public abstract class BaseActivity<T extends BasePresenter> extends AppCompatActivity implements BaseView {@Inject
    public T presenter;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
        //去掉Activity上面的状态栏
        getWindow().setFlags(WindowManager.LayoutParams. FLAG_FULLSCREEN , WindowManager.LayoutParams. FLAG_FULLSCREEN);
        super.onCreate(savedInstanceState);
        initPresenter();
        initView();
        if (Build.VERSION.SDK_INT >= 21) {View decorView = getWindow().getDecorView();
            int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
            decorView.setSystemUiVisibility(option);
            getWindow().setStatusBarColor(Color.TRANSPARENT);
        }}public abstract void initPresenter();
    public abstract void initView();

    @Override
    public void startProgress() {if (!ProgressDlgUtil.isShowing()){ProgressDlgUtil.showSuccinctProgress(this,"正在验证中...",2,false,false);
        }}@Override
    public void stopProgress() {ProgressDlgUtil.dismiss();
    }
}

很简单,定义一个抽象的方法initPresenter();实现BaseView接口,使用泛型获取Presenter的对象,由实现它的子类做具体实现, 相信很好理解,

然后我们再来看看LoginActivity的部分
public class LoginActivity extends BaseActivity<LoginPresenter> implements InterfaceContract.LoginView, View.OnClickListener {private ActivityLoginBinding binding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);
    }@Override
    public void initPresenter() {//完成依赖
        DaggerLoginCompent.builder().loginModule(new LoginModule(this)).build().inject(this);
    }@Override
    public void initView() {binding = DataBindingUtil.setContentView(this, R.layout.activity_login);
        binding.btLogin.setOnClickListener(this);
    }@Override
    protected void onDestroy() {presenter.detachView();
        super.onDestroy();
    }@Override
    public String getUserName() {String name = binding.etUser.getText().toString().trim();
        return name;
    }@Override
    public String getPassWord() {String md5PassWord = MD5Utils.md5(binding.etPwd.getText().toString().trim()).toLowerCase();
        return md5PassWord;
    }@Override
    public void loginSuccess() {Intent intent = new Intent(this,MainActivity.class);
        startActivity(intent);
        finish();
    }@Override
    public void loginFail() {Toast.makeText(this,"登陆失败",Toast.LENGTH_LONG).show();
    }@Override
    public void onClick(View view) {presenter.login();
    }
}

LoginActivity继承自BaseBactivity 实现了LoginView接口,本项目才用DataBing绑定获取对象(DataBing的绑定可以自行百度,减少FindViewById的操作)。在initPresenter中

通过Dagger2注解,来获取Presenter的对象, 因为内容较多,Dagger2的用法,将在下次讲解,本次只介绍MVP的内容如何应用到项目中。可以看到V层获取到presenter
的对象以后,通过点击事件,调用login()方法,这时逻辑就到了P层,然后我们再来看看LoginPresenter的代码:     
public class LoginPresenter extends BasePresenter<LoginActivity> implements InterfaceContract.OnLoginListener{//    private InterfaceContract.LoginView mView;
    private LoginModelImple modelImple;

    @Inject
    public LoginPresenter(InterfaceContract.LoginView mView){attachView((LoginActivity) mView);
        modelImple = new LoginModelImple();
    }public void login(){mView.startProgress();
        String userword = mView.getUserName();
        String passWord = mView.getPassWord();
        modelImple.login(userword,passWord,this);
    }@Override
    public void LoginSucess() {mView.stopProgress();
        mView.loginSuccess();
    }@Override
    public void LoginFail() {mView.stopProgress();
        mView.loginFail();
    }
}

同样很简单,思路也很清晰, 通过构造方法获取V层的对象,然后通过传捡来的这个对象,获取user的账号密码,在构造方法中处理化M层的对象,调用M层login()方法,处理登陆的逻辑就到了M层,我们再来看看M层的逻辑,

public class LoginModelImple implements InterfaceContract.ILoginModule{public Context context;
    @Override
    public void login(String userName, String passWord, final InterfaceContract.OnLoginListener listener) {Observable<BaseEntity<UserInfo>> observable = RetrofitFactory.builder().getService().login(userName,passWord);
        observable.compose(RxSchedulers.compose()).subscribe(new BaseObserver<UserInfo>(VKOApplication.getInstance()) {@Override
            protected void onHandleSuccess(UserInfo userInfo) {LogUtils.d(this,"登陆请求的回调-------");
                LogUtils.d(this,"userInfo.getToken() = " + userInfo.getToken());
                SPUtils.put(VKOApplication.getInstance(),"user_token",userInfo.getToken());
                // 保存用户信息等操作
                listener.LoginSucess();
            }});
    }
}
同样的,M层login方法用来处理登陆请求成功 以及 失败对应的方法,我们可以看到,onHandleSucces方法中,回调了P层的登陆成功的方法(登陆失败已经封装到Obseable中,
有兴趣的可以看看)
然后我们再回到P层中,可以看到到,LgoinSucess()方法中,做了两件事,隐藏进度条,回调V层。 然后交给 V层来处理登陆成功和失败的相关操作,
再来看看LoginAcitivity中,登陆成功跳转MainActivity ,失败则提示用户账号或密码错误, 整个登陆的逻辑就完成了。可以发现在这个过程中,我们的思路
非常清晰, 整个流程采用接口回调的方式,让代码更整洁清除,同时完成了V层和M层的解耦操作。
V层只负责更新UI  而处理耗时操作的逻辑都放在了M层, P层则是连接M和V的桥梁。 好了MVP运用到项目中就到这,下一章我将给大家介绍,如何结合MVP
使用Retrofit+okhttp等android现在流行的框架。
项目地址 :https://github.com/yy-Kevin/MVP-Dagger-Rxjava2-Retrofit

MVP+Dragger2+Rxjava2+Retrofit+OKhttp进行开发。相关推荐

  1. 新闻APP前台和后台管理系统 MVP+Dragger2+RxJava+RetroFit

    一 系统说明 该新闻资讯APP 主要是用户可以查看各种各样的新闻资讯,并且可以进行注册,登录账号,评论,收藏,取消收藏,浏览新闻,发布新闻,修改修改,删除新闻,用户管理,个人信息等操作,该APP分为前 ...

  2. Dagger2之应用篇(Dagger2+RxJava+Retrofit+OkHttp+MVP)-第7章

    介绍 前面介绍了Dagger2,今天尝试自己的想法去应用了下,说实话很别扭,晚上睡觉思前想后这个的好处.总是有一种似懂非懂,感觉就是,让对象与对象之间产生了一中关联,多个module的provides ...

  3. java二次封装_基于OKhttp+Rxjava2+Retrofit进行二次封装

    概述 基于Retrofit进行二次封装,优雅的初始化设置.基于Okhttp拦截器和基础缓存,封装了无网络和其他所有场景的缓存策略支持,以及频繁调用请求的丢弃策略. 特性 1.基于Retrofit的二次 ...

  4. 模仿开眼的视频APP,基于MVP+rxjava2+Retrofit+Dagger2+Glide+Realm+GSYVideoPlayer

    EyesOpener EyesOpener,一款开眼高仿APP, 基于 MVP+rxjava2+Retrofit+![Dagger2](https://img-blog.csdn.net/201806 ...

  5. Android MVVM + Retrofit + OkHttp + Coroutine 协程 + Room + 组件化架构的Android应用开发规范化架构

    BaseDemo 介绍 BaseDemo 是Android MVVM + Retrofit + OkHttp + Coroutine 协程 + Room + 组件化架构的Android应用开发规范化架 ...

  6. android retrofit入门,Android开发 retrofit入门讲解

    前言 retrofit基于okhttp封装的网络请求框架,网络请求的工作本质上是 OkHttp 完成,而 retrofit 仅负责网络请求接口的封装.如果你不了解OKhttp建议你还是先了解它在来学习 ...

  7. 简单java登录页面android_Android 之路 - RxJava2+Retrofit实现简单登陆

    原标题:Android 之路 - RxJava2+Retrofit实现简单登陆 前言 使用RxJava2+Retrofit实现简单登陆. 正文1. Hello world1.1 相关版本 Androi ...

  8. Retrofit+OKHttp+RxJava的使用

    什么是响应式编程   响应式编程是一种基于异步数据 流概念的编程模式.数据流就像一条河:它可以被观测,被过滤,被操作,或者为新的消费者与另外一 条流合并为一条新的流. 什么是RxJava RxJava ...

  9. (三)Rxjava2+Retrofit之文件上传与下载

    结合 第一篇文章对Retrofit的封装,本篇文章将讲述如何实现文件上传与下载.本篇文章可分为文件上传与文件下载两部分内容. 一.使用RxJava+Retrofit上传文件 使用Retrofit上传文 ...

最新文章

  1. Android桌面组件App Widget开发三步走
  2. Java中的参数传递 --Java
  3. 直通车运营系统优化之账户结构设置
  4. Bootstrap框架学习
  5. 在XNA 3.0 项目添加声音——播放MP3或WMA声音文件
  6. 组合,聚合,关联,依赖的区别
  7. 想加入一行代码吗?使用code标签
  8. 服务器内存太小,伤不起![异常与应用程序池引发的连锁命案]
  9. 二年级计算机考试题,二年级计算机笔测试题(XX-XX第一学期
  10. HTML5期末大作业:我的家乡网站设计4
  11. WIn10桌面美化(一)Rainmeter的使用
  12. 小程序随笔(关于香港手机号无法接收短信)
  13. 通过抓包来看http三次握手的具体细节
  14. 成果丰硕!SWORD 斯沃德惊艳亮相“第18届深圳名品家博会”
  15. raid 物理盘缓存状态_查看RAID状态
  16. mac android 文件管理器,PC和Mac浏览安卓手机上文件最快的方式,只需两步
  17. 近期工作心得(总结篇)
  18. 连接华为云服务中心常见问题汇总
  19. 西铁城s621c打印机调试说明,西铁城CL-S621CII驱动
  20. 从软件测试培训班出来后找工作这段时间的经历,教会了我这五件事...

热门文章

  1. 玩游戏用什么轴的机械键盘好_机械键盘轴哪个最适合打游戏
  2. 面试问烂了的测试用例: 登录界面的测试用例
  3. ant安装和ant的环境配置
  4. GHM:Gradient Harmonized Single-stage Detector
  5. 手机被DNS劫持后的更改方案
  6. python读写tif文件
  7. JAVA冰箱评测开题报告_基于CFD的风冷冰箱后风道数值计算和优化设计开题报告...
  8. 【Linux】通过Mac终端连接虚拟机(ssh root@192.168.31.230)
  9. STM32 (基于HAL库) 硬件IIC读写任意AT24CXX芯片
  10. 在湖北考取的交通类安全员B证可以调转河南省企业使用吗?