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中返回。
先看契约类,其中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 开发 ...
随机推荐
- MySQL union 和 order by 同时使用
目录 一.出现错误的情况 二.解决上述问题的两种方法 三.案例分析: 求解: 常见的错误解法 (1)使用 union 和 多个order by 不加括号 [报错] (2)order by 在 unio ...
- ionic+vue+capacitor系列笔记--02项目中集成Capacitor,添加android,ios平台,真机运行项目
Capacitor是什么? Capacitor是由ionic团队开发的一款跨平台移动应用构建工具,可轻让我们轻松的构建Android.iOS.Electron和Web应用程序. Capacitor是A ...
- 移动 WEB 布局方式之 rem 适配布局 ---- 苏宁首页案例制作
一.技术选型 二.搭建相关文件夹结构 三.设置视口标签以及引入初始化样式 四.设置公共common.less 文件 common.less //设置常见的屏幕尺寸大小,修改里面的html 文字大小 / ...
- vue学习笔记(一) ---- vue指令(总体大纲)
一.什么是Vue 官方文档:https://cn.vuejs.org/v2/guide/ 关键字: 渐进式框架 自底向上增量开发 视图层 单文件组件 复杂的单页应用 复杂的单页应用: 顾名思义,单页应 ...
- php7.3的安装以及在Apache中部署php
安装 php7.3 1.进入php官网:https://www.php.net/downloads.php 2.点击 Windows downloads 3.下载压缩包 4.将下载好的压缩包解压,可选 ...
- 12月5日内容总结——JS基础知识及变量常量、基本数据类型、运算符、流程控制、函数、内置对象
目录 一.JS简介 简介 ECMAScript的历史 二.JS基础 1.注释语法 2.引入js的多种方式 3.结束符号 三.变量与常量 编写和运行js代码的两种方式 变量声明 四.基本数据类型 1.数 ...
- 编程哲学之 C# 篇:006——什么是 .NET
本章将用本系列第二章中提到的 类比 思维来让读者快速了解什么是.NET. 当年在网上看到一个初学者问<Java编程思想>第一章看不懂怎么办.然后我发现在很多经典的技术书中,如<C#入 ...
- pdf转MD、HTML、word网址收集
PDF 转 Word,Excel,PPT,JPG 的网址:https://smallpdf.com/cn/pdf-to-word PDF 转 Markdown 的网址:https://pdf2md.m ...
- 如何让别人pip install自己写的库?
一. 构建项目目录结构 结构如图所示: 文件介绍:LICENSE和README.md在git建仓库时选上,克隆下来就会有,license最好选择MIT的.sort.py文件里随便写个方法用于直接调用: ...
- Java基础语法:类型转换、变量、常量
Java基础语法:类型转换.变量.常量 类型转换 低---------->高 byte,short,char->int->long->float->double 从高到低 ...