Android MVP框架 详细代码
android mvp的好处,网上一搜一大堆,相对于一开始普通的在activity中处理所有的不管是网络请求还是页面渲染,最大的好处是简洁了,废话不多说,看代码
这里网络请求使用了两种,一种是自己封装的okhttp,一种是retrofit+rxjava,可以看出retrofit+rxjava的链式调用和普通的okhttp的区别
mvp,m-model 处理数据,v-activity渲染展示,p-persenter 用于连接m和v,其中又引入锲约类的概念,用于管理这三个所有的接口。
先看代码,
 ,为了方便我直接放在一个包里了,可以看到 有TestActivity,(mvp-v),TestModel(mvp-m),TestPersenter(mvp-p),其中TestContract就是契约类,用于管理用到的所有接口,多了一个TestCallback用于使用自己封装的okhttp回调,使用retrofit+rxjava时可以省略,这其中也有人习惯把TestModel省略,直接在Persenter中处理数据然后在view中返回。
,为了方便我直接放在一个包里了,可以看到 有TestActivity,(mvp-v),TestModel(mvp-m),TestPersenter(mvp-p),其中TestContract就是契约类,用于管理用到的所有接口,多了一个TestCallback用于使用自己封装的okhttp回调,使用retrofit+rxjava时可以省略,这其中也有人习惯把TestModel省略,直接在Persenter中处理数据然后在view中返回。
先看契约类,其中BaseView可以提取一些公共的方法
public interface TestContract {
    interface TestModel{
        void getData(String id,TestCallback callback);
        Observable<HomePage> getData();
    }
    interface TestPersenter{
        void getData(String id);
    }
    interface TestView extends BaseView {
       void SetData(HomePage homePage);
    }
}
public interface BaseView {
    void Toast(String s);
    /**
     * 绑定Android生命周期 防止RxJava内存泄漏
     *
     * @param <T>
     * @return
     */
    <T> AutoDisposeConverter<T> bindAutoDispose();
}
可以清楚的看到,model,persenter,view使用到的接口。
再看activity中,implements TestContract.TestView接口,必须实现接口中的方法----SetData,定义了一个按钮,一个TextView,点击按钮,获取数据,显示在TextView中,其中TestPersenter testPersenter = new TestPersenter(this);体现了persenter的连接作用,获取到实例,调用persenter中的getData方法,
public class TestActivity extends BaseActivity implements TestContract.TestView {
    TestPersenter testPersenter = new TestPersenter(this);
    @BindView(R.id.button)
    Button button;
    @BindView(R.id.testview)
    TextView testview;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test);
        ButterKnife.bind(this);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                testPersenter.getData("1");
            }
        });
    }
    @Override
    public void SetData(HomePage homePage) {
        testview.setText(homePage.getMessage());
    }
    @Override
    public void Toast(String s) {
        super.Toast(s);
    }
}
public class BaseActivity extends AppCompatActivity implements BaseView {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_base2);
        Window window = getWindow();
        window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        getSupportActionBar().hide();
        ImmersionBar.with(this)
                .statusBarColor(R.color.bar)     //状态栏颜色,不写默认透明色
                .statusBarDarkFont(true) //原理:如果当前设备支持状态栏字体变色,会设置状态栏字体为黑色,如果当前设备不支持状态栏字体变色,会使当前状态栏加上透明度,否则不执行透明度
                .fitsSystemWindows(true)
                .keyboardEnable(true)
                .init();
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 必须调用该方法,防止内存泄漏
        ImmersionBar.destroy(this,null);
    }
    /**
     * 绑定生命周期 防止MVP内存泄漏
     *
     * @param <T>
     * @return
     */
    @Override
    public <T> AutoDisposeConverter<T> bindAutoDispose() {
        return AutoDispose.autoDisposable(AndroidLifecycleScopeProvider
                .from(this, Lifecycle.Event.ON_DESTROY));
    }
    @Override
    public void Toast(String s) {
    }
}
TestPersenter,首先implements 接口,实现接口中的方法---getData,其次拿到了model和view,在getData方法中,调用model获取数据,调用view的setData方法展示数据到页面,从这里也可以看出persenter的连接作用,连接model和view。
public class TestPersenter implements TestContract.TestPersenter{
    TestContract.TestModel model ;
    TestContract.TestView testView;
    public TestPersenter(TestContract.TestView testView) {
        this.testView = testView;
        this.model = new TestModel();
    }
    @Override
    public void getData(String id) {
        model.getData("1", new TestCallback() {
            @Override
            public <T> void success(T enty) {
                testView.SetData((HomePage) enty);
            }
            @Override
            public void error(String msg) {
            }
        });
    }
}
model:同样implements接口,实现接口中的方法getData,第一个方法是使用自己封装的okhttp网络类,在这里就看出TestCallback 的作用了,访问接口获取数据后,通过TestCallback 返回,TestCallback 中只定义了两个简单的,一个成功时的回调,一个失败时的回调
public class TestModel implements TestContract.TestModel {
    @Override
    public void getData(String id, TestCallback callback) {
        new OkHttpUtil().getJson(HttpUrl.homePage, new OkHttpUtil.HttpCallBack() {
            @Override
            public void onSusscess(String data) throws JSONException, ParseException {
                HomePage homePage = new Gson().fromJson(data,HomePage.class);
                if(homePage.isSuccess()){
                    callback.success(homePage);
                }else{
                    callback.error(homePage.getMessage());
                }
            }
            @Override
            public void onError(String meg) {
                super.onError(meg);
                callback.error(meg);
            }
        });
    }
    @Override
    public Observable<HomePage> getData() {
return RetrofitClient.getInstance().getApi().GetData();
}
}
public interface TestCallback {
    <T> void success(T enty);
    void error(String msg);
}
使用retrofit+rxjava,可以看到,省略了TestCallback回调,直接链式调用,onNext中调用了view的setData方法显示数据。
public class TestPersenter implements TestContract.TestPersenter{
    TestContract.TestModel model ;
    TestContract.TestView testView;
    public TestPersenter(TestContract.TestView testView) {
        this.testView = testView;
        this.model = new TestModel();
    }
    @Override
    public void getData(String id) {
//        model.getData("1", new TestCallback() {
//            @Override
//            public <T> void success(T enty) {
//                testView.SetData((HomePage) enty);
//            }
//
//            @Override
//            public void error(String msg) {
//
//            }
//        });
        model.getData()
            .compose(RxScheduler.Obs_io_main())
            .to(studyView.bindAutoDispose())
            .subscribe(new Observer<HomePage>() {
                @Override
                public void onSubscribe(@NonNull Disposable d) {
                }
                @Override
                public void onNext(@NonNull HomePage homePage) {
                    testView.SetData(homePage);
                }
                @Override
                public void onError(@NonNull Throwable e) {
           
) } @Override public void onComplete() { } }); } }
retrofit的使用到的方法

public interface APIService {
    /**
     * 首页数据
     * @return
     */
    @GET("app/home_page/queryList")
    Observable<HomePage> GetData();
}
public class RetrofitClient {
    private static volatile RetrofitClient instance;
    private APIService apiService;
    private String baseUrl = "****";
    private Retrofit retrofit;
    private OkHttpClient okHttpClient;
    private RetrofitClient() {
    }
    public static RetrofitClient getInstance() {
        if (instance == null) {
            synchronized (RetrofitClient.class) {
                if (instance == null) {
                    instance = new RetrofitClient();
                }
            }
        }
        return instance;
    }
    /**
     * 设置Header
     *
     * @return
     */
    private Interceptor getHeaderInterceptor() {
        return new Interceptor() {
            @Override
            public Response intercept(@NonNull Chain chain) throws IOException {
                Request original = chain.request();
                Request.Builder requestBuilder = original.newBuilder();
                //添加Token
//                        .header("token", "");
                Request request = requestBuilder.build();
                return chain.proceed(request);
            }
        };
    }
    /**
     * 设置拦截器 打印日志
     *
     * @return
     */
    private Interceptor getInterceptor() {
        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
        //显示日志
        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        return interceptor;
    }
    public OkHttpClient getOkHttpClient() {
        if (okHttpClient == null) {
            //如果为DEBUG 就打印日志
            if (BuildConfig.DEBUG) {
                okHttpClient = new OkHttpClient().newBuilder()
                        //设置Header
                        .addInterceptor(getHeaderInterceptor())
                        //设置拦截器
                        .addInterceptor(getInterceptor())
                        .build();
            } else {
                okHttpClient = new OkHttpClient().newBuilder()
                        //设置Header
                        .addInterceptor(getHeaderInterceptor())
                        .build();
            }
        }
        return okHttpClient;
    }
    public APIService getApi() {
        //初始化一个client,不然retrofit会自己默认添加一个
        if (retrofit == null) {
            retrofit = new Retrofit.Builder()
                    //设置网络请求的Url地址
                    .baseUrl(baseUrl)
                    //设置数据解析器
                    .addConverterFactory(GsonConverterFactory.create())
                    //设置网络请求适配器,使其支持RxJava与RxAndroid
                    .addCallAdapterFactory(RxJava3CallAdapterFactory.create())
                    .client(getOkHttpClient())
                    .build();
        }
        //创建—— 网络请求接口—— 实例
        if (apiService==null){
            apiService = retrofit.create(APIService.class);
        }
        return apiService;
    }
}
public class RxScheduler {
    /**
     * 统一线程处理
     *
     * @param <T> 指定的泛型类型
     * @return FlowableTransformer
     */
    public static <T> FlowableTransformer< T, T> Flo_io_main() {
        return new FlowableTransformer<T, T>() {
            @Override
            public Publisher<T> apply(Flowable<T> upstream) {
                return upstream.subscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread());
            }
        };
    }
    /**
     * 统一线程处理
     *
     * @param <T> 指定的泛型类型
     * @return ObservableTransformer
     */
    public static <T> ObservableTransformer<T, T> Obs_io_main() {
        return new ObservableTransformer<T, T>() {
            @Override
            public ObservableSource<T> apply( Observable<T> upstream) {
                return upstream.subscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread());
            }
        };
    }
}
public interface BaseView {
    void Toast(String s);
    /**
     * 绑定Android生命周期 防止RxJava内存泄漏
     *
     * @param <T>
     * @return
     */
    <T> AutoDisposeConverter<T> bindAutoDispose();
}
//okhttp3
implementation 'com.squareup.okhttp3:okhttp:4.2.0'
implementation "com.squareup.okhttp3:logging-interceptor:3.10.0"
implementation 'com.google.code.gson:gson:2.8.6' //retrofit2
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'com.squareup.retrofit2:adapter-rxjava3:2.9.0' //AutoDispose解决RxJava内存泄漏
implementation 'com.uber.autodispose2:autodispose:2.0.0'
implementation 'com.uber.autodispose2:autodispose-android:2.0.0'
implementation 'com.uber.autodispose2:autodispose-lifecycle:2.0.0'
implementation 'com.uber.autodispose2:autodispose-androidx-lifecycle:2.0.0'
// 基础依赖包,必须要依赖
implementation 'com.gyf.immersionbar:immersionbar:3.0.0-beta07'
// fragment快速实现(可选)
implementation 'com.gyf.immersionbar:immersionbar-components:3.0.0-beta07'
至此,mvp框架结束,mvp增加了接口,使页面和数据处理分开,层次分明,后期好维护。在较小项目中,就几个页面,不必使用框架,也不必为了框架而使用,适合项目的才是最好的。
Android MVP框架 详细代码的更多相关文章
- 如何实现自己的Android MVP框架?
		相信熟悉android开发的童鞋对MVP框架应该都不陌生吧,网上很多关于android中实现MVP的文章,大家可以直接搜索学习.这些文章中,MVP的实现思路基本都是把Activity.Fragment ... 
- android MVP框架
		原文地址:http://blog.csdn.net/guxiao1201/article/details/40147209 在开发Android应用时,相信很多同学遇到和我一样的情况,虽然项目刚开始构 ... 
- Android MVP框架模式
		结合前一篇MVC框架模式 为了更好地细分视图(View)与模型(Model)的功能,让View专注于处理数据的可视化以及与用户的交互,同时让Model只关系数据的处理,基于MVC概念的MVP(Mode ... 
- Android MVP框架实现登录案例
		一.Model package com.czhappy.mvpdemo.model; /** * author: chenzheng * created on: 2019/5/16 11:06 * d ... 
- Android MVP Presenter 中引发的空指针异常
		一.概述 最近对 googlesamples/android-architecture 中的 MVP-dagger 进行了学习.对照项目的 MVP-dagger 分支,对 MVP-dagger 进行了 ... 
- android mvp高速开发框架介绍(继续dileber)
		android mvp框架:dileber(https://github.com/dileber/dileber.git) 继续为大家介绍android mvp开源框架 dileber 官方交流qq群 ... 
- android mvp高速开发框架介绍(dileber的简单介绍)
		今天我为大家介绍一款android mvp框架:dileber(https://github.com/dileber/dileber.git) 官方交流qq群:171443726 我个人qq:2971 ... 
- android mvp高速开发框架介绍(dileber使用之图片下载工具)
		这几天忙着工作- 今天抽时间又把框架的bug处理了一下--并且把volley的源代码改动了一下 android mvp框架:dileber(https://github.com/dileber/dil ... 
- android mvp高速开发框架介绍(dileber使用之小工具使用)
		android mvp框架:dileber(https://github.com/dileber/dileber.git) 继续为大家介绍android mvp开源框架 dileber 官方交流qq群 ... 
- 【腾讯Bugly干货分享】一步一步实现Android的MVP框架
		本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/5799d7844bef22a823b3ad44 内容大纲: Android 开发 ... 
随机推荐
- 5、Idea同时选择多处光标进行编辑
			1.按住Alt+Shift,然后用鼠标左键点击文本,可以让光标在多个位置出现2.每个光标都会同时输入你正在输入的文本3.ESC退出 搜索 复制 
- 三台服务器使用docker搭建redis一主二从三哨兵,概念-搭建-整合springboot
			一.前言 redis在我们企业级开发中是很常见的,但是单个redis不能保证我们的稳定使用,所以我们要建立一个集群. redis有两种高可用的方案: High availability with Re ... 
- [OpenCV实战]32 使用OpenCV进行非真实感渲染
			目录 1 保边滤波的频域变换 1.1 保边滤波器Edge Preserving Filter 1.1.1 函数调用 1.1.2 edgePreservingFilter结果 1.2 细节增强 1.3 ... 
- 《STL源码剖析》STL迭代器分类
			input迭代器:只能向前移动,一次一步,用户只能读取,不能修改它们所指向的东西,而且只能读取一次. output迭代器情况类似,但一切只为输出:它们只能向前移动,一次一步,用户只可以修改它们所指向的 ... 
- 引子 - 实现轻量的 ioc 容器
			IoC 反转控制原则也被叫做依赖注入 DI, 容器按照配置注入实例化的对象. 假设 A 的相互依赖关系如下图, 如何将 A 对象实例化并注入属性. 本文将实现一个轻量化的 IoC 容器, 完成对象的实 ... 
- final关键字用于修饰局部变量-final关键字用于修饰成员变量
			final关键字用于修饰局部变量 局部变量--引用类型 引用类型的局部变量,被final修饰后,只能指向一个对象,地址不能再更改.但是不影响对象内部的成员变量值的 修改,代码如下: public cl ... 
- final关键字用于修饰类-final关键字用于修饰成员方法
			final关键字与四种用法 概念 学习了继承后,我们知道,子类可以在父类的基础上改写父类内容容,比如,方法重写.那么我们能不能随意的继承 API中提供的类,改写其内容呢?显然这是不合适的.为了避免这种 ... 
- 对象数组- 什么是ArrayList类
			对象数组 引入--对象数组 使用学生数组,存储三个学生对象,代码如下: public class Student { private String name; private int age; pub ... 
- avalonia实现自定义小弹窗
			对于使用avalonia的时候某些功能需要到一些提示,比如异常或者成功都需要对用户进行提示,所以需要单独实现弹窗功能,并且可以自定义内部组件,这一期将手动实现一个简单的小弹窗,并且很容易自定义 创建项 ... 
- Android第六次作业
			图片一 用内部存储实现文件写入和读取功能 <?xml version="1.0" encoding="utf-8"?> <LinearLayo ... 
