【Android架构】基于MVP模式的Retrofit2+RXjava封装
最近有个新项目要做,搭建框架的时候,顺便梳理了下MVP模式,特此记录,欢迎大家指正。
项目地址:https://github.com/18702953620/MVPDemo
一 、首先是依赖
compile 'com.google.code.gson:gson:2.8.0' compile 'com.squareup.okhttp3:okhttp:3.4.1' compile 'com.yanzhenjie:permission:1.0.5' compile 'com.squareup.retrofit2:retrofit:2.3.0' compile 'io.reactivex.rxjava2:rxandroid:2.0.1' compile 'io.reactivex.rxjava2:rxjava:2.1.5' //ConverterFactory的String依赖包 compile 'com.squareup.retrofit2:converter-scalars:2.3.0' //ConverterFactory的Gson依赖包 compile 'com.squareup.retrofit2:converter-gson:2.3.0' //CallAdapterFactory的Rx依赖包 compile 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
二、ApiServer,定义了一些接口
public interface ApiServer { @POST("shopping_login.htm") Observable<String> LoginByRx(@Field("username") String username, @Field("password") String password); }
三、ApiRetrofit,初始化Retrofit、OkHttpClient,加入了拦截器
public class ApiRetrofit { public final String BASE_SERVER_URL = "https://wawa-api.vchangyi.com/"; private static ApiRetrofit apiRetrofit; private Retrofit retrofit; private OkHttpClient client; private ApiServer apiServer; private String TAG = "ApiRetrofit"; /** * 请求访问quest * response拦截器 */ private Interceptor interceptor = new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); long startTime = System.currentTimeMillis(); Response response = chain.proceed(chain.request()); long endTime = System.currentTimeMillis(); long duration = endTime - startTime; MediaType mediaType = response.body().contentType(); String content = response.body().string(); Log.e(TAG, "----------Request Start----------------"); Log.e(TAG, "| " + request.toString() + request.headers().toString()); Log.e(TAG, "| Response:" + content); Log.e(TAG, "----------Request End:" + duration + "毫秒----------"); return response.newBuilder() .body(ResponseBody.create(mediaType, content)) .build(); } }; public ApiRetrofit() { client = new OkHttpClient.Builder() //添加log拦截器 .addInterceptor(interceptor) .connectTimeout(10, TimeUnit.SECONDS) .readTimeout(10, TimeUnit.SECONDS) .build(); retrofit = new Retrofit.Builder() .baseUrl(BASE_SERVER_URL) .addConverterFactory(GsonConverterFactory.create()) .addConverterFactory(ScalarsConverterFactory.create()) //支持RxJava2 .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .client(client) .build(); apiServer = retrofit.create(ApiServer.class); } public static ApiRetrofit getInstance() { if (apiRetrofit == null) { synchronized (Object.class) { if (apiRetrofit == null) { apiRetrofit = new ApiRetrofit(); } } } return apiRetrofit; } public ApiServer getApiService() { return apiServer; } }
四、基类
1.BaseView,其中定义了常用的接口
public interface BaseView { /** * 显示dialog */ void showLoading(); /** * 隐藏 dialog */ void hideLoading(); /** * 显示错误信息 * * @param msg */ void showError(String msg); /** * 错误码 */ void onErrorCode(BaseModel model); }
2.BaseModel
public class BaseModel<T> implements Serializable { private int errcode; private String errmsg; private T result; public int getErrcode() { return errcode; } public void setErrcode(int errcode) { this.errcode = errcode; } public String getErrmsg() { return errmsg; } public void setErrmsg(String errmsg) { this.errmsg = errmsg; } public T getResult() { return result; } public void setResult(T result) { this.result = result; } }
3.BasePresenter
public class BasePresenter<V extends BaseView> { private CompositeDisposable compositeDisposable; public V baseView; protected ApiServer apiServer = ApiRetrofit.getInstance().getApiService(); public BasePresenter(V baseView) { this.baseView = baseView; } /** * 解除绑定 */ public void detachView() { baseView = null; removeDisposable(); } /** * 返回 view * * @return */ public V getBaseView() { return baseView; } public void addDisposable(Observable<?> observable, BaseObserver observer) { if (compositeDisposable == null) { compositeDisposable = new CompositeDisposable(); } compositeDisposable.add(observable.subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribeWith(observer)); } public void removeDisposable() { if (compositeDisposable != null) { compositeDisposable.dispose(); } } }
4.BaseObserver,主要处理了常见的错误
public abstract class BaseObserver<T> extends DisposableObserver<T> { protected BaseView view; /** * 解析数据失败 */ public static final int PARSE_ERROR = 1001; /** * 网络问题 */ public static final int BAD_NETWORK = 1002; /** * 连接错误 */ public static final int CONNECT_ERROR = 1003; /** * 连接超时 */ public static final int CONNECT_TIMEOUT = 1004; public BaseObserver(BaseView view) { this.view = view; } @Override protected void onStart() { if (view != null) { view.showLoading(); } } @Override public void onNext(T o) { try { BaseModel model = (BaseModel) o; if (model.getErrcode() == 0) { onSuccess(o); } else { if (view != null) { view.onErrorCode(model); } } } catch (Exception e) { e.printStackTrace(); onError(e.toString()); } } @Override public void onError(Throwable e) { if (view != null) { view.hideLoading(); } if (e instanceof HttpException) { // HTTP错误 onException(BAD_NETWORK); } else if (e instanceof ConnectException || e instanceof UnknownHostException) { // 连接错误 onException(CONNECT_ERROR); } else if (e instanceof InterruptedIOException) { // 连接超时 onException(CONNECT_TIMEOUT); } else if (e instanceof JsonParseException || e instanceof JSONException || e instanceof ParseException) { // 解析错误 onException(PARSE_ERROR); } else { if (e != null) { onError(e.toString()); } else { onError("未知错误"); } } } private void onException(int unknownError) { switch (unknownError) { case CONNECT_ERROR: onError("连接错误"); break; case CONNECT_TIMEOUT: onError("连接超时"); break; case BAD_NETWORK: onError("网络问题"); break; case PARSE_ERROR: onError("解析数据失败"); break; default: break; } } @Override public void onComplete() { if (view != null) { view.hideLoading(); } } public abstract void onSuccess(T o); public abstract void onError(String msg); }
5.BaseActivity,实现BaseView,处理了Presenter的生命周期。
public abstract class BaseActivity<P extends BasePresenter> extends AppCompatActivity implements BaseView { public Context context; private ProgressDialog dialog; public Toast toast; protected P presenter; protected abstract P createPresenter(); protected abstract int getLayoutId(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); context = this; setContentView(getLayoutId()); presenter = createPresenter(); initView(); initData(); } public void initData() { } public void initView() { } @Override protected void onDestroy() { super.onDestroy(); if (presenter != null) { presenter.detachView(); } } /** * @param s */ public void showtoast(String s) { if (toast == null) { toast = Toast.makeText(getApplicationContext(), s, Toast.LENGTH_LONG); } toast.show(); } private void closeLoadingDialog() { if (dialog != null && dialog.isShowing()) { dialog.dismiss(); } } private void showLoadingDialog() { if (dialog == null) { dialog = new ProgressDialog(context); } dialog.setCancelable(false); dialog.show(); } @Override public void showLoading() { showLoadingDialog(); } @Override public void hideLoading() { closeLoadingDialog(); } @Override public void showError(String msg) { showtoast(msg); } @Override public void onErrorCode(BaseModel model) { } @Override public void showLoadingFileDialog() { showFileDialog(); } @Override public void hideLoadingFileDialog() { hideFileDialog(); } @Override public void onProgress(long totalSize, long downSize) { if (dialog != null) { dialog.setProgress((int) (downSize * 100 / totalSize)); } } }
五、如上,框架已经搭建好了,让我们来看看在实际项目中怎么用。
我们来模拟登陆
1.定义LoginView 继承于BaseView
public interface LoginView extends BaseView { void onLoginSucc(); }
2.定义LoginPresenter 继承于BasePresenter
public class LoginPresenter extends BasePresenter<LoginView> { public LoginPresenter(LoginView baseView) { super(baseView); } public void login(String name, String pwd) { addDisposable(apiServer.LoginByRx(name, pwd), new BaseObserver(baseView) { @Override public void onSuccess(Object o) { baseView.onLoginSucc(); } @Override public void onError(String msg) { baseView.showError(msg); } }); } }
3.LoginActivity 中使用
public class LoginActivity extends BaseActivity<LoginPresenter> implements LoginView { private AutoCompleteTextView mEmailView; private EditText mPasswordView; @Override protected LoginPresenter createPresenter() { return new LoginPresenter(this); } @Override protected int getLayoutId() { return R.layout.activity_login; } @Override public void initView() { mEmailView = (AutoCompleteTextView) findViewById(R.id.email); mPasswordView = (EditText) findViewById(R.id.password); Button mEmailSignInButton = (Button) findViewById(R.id.email_sign_in_button); mEmailSignInButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { //示例代码,示例接口 presenter.login(mEmailView.getText().toString(), mPasswordView.getText().toString()); } }); } @Override public void onLoginSucc() { //Login Succ showtoast("登录成功"); } }
以上就是MVP的实现,MVP的框架很多,适合自己就好。
原文发布时间为:2018-07-31
本文作者: chenghuan3
本文来自云栖社区合作伙伴“ 安卓巴士Android开发者门户”,了解相关信息可以关注“ 安卓巴士Android开发者门户”。
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
微信多媒体团队梁俊斌访谈:聊一聊我所了解的音视频技术
本文内容由“微信多媒体团队”整理发布。 1、引言 广州TIT创意园,这里是腾讯在广州的研发团队所在地,LiveVideoStack采访了微信多媒体内核中心音视频算法高级工程师梁俊斌(Denny)。从华为2012实验室到腾讯,过去十余年梁俊斌一直专注在音频技术。他告诉LiveVideoStack:音频技术还有许多难点需要解决,而作为技术人也延展到应用场景,关注用户需求。本文整理了本次访谈的主要内容,仅供参阅。 学习交流: - 即时通讯开发交流3群:185926912[推荐] - 移动端IM开发入门文章:《新手入门一篇就够:从零开发移动端IM》 (本文同步发布于:http://www.52im.net/thread-1828-1-1.html) 2、相关文章 《微信团队分享:视频图像的超分辨率技术原理和应用场景》 《微信团队分享:微信每日亿次实时音视频聊天背后的技术解密》 《微信团队分享:微信Android版小视频编码填过的那些坑》 《微信多媒体团队访谈:音视频开发的学习、微信的音视频技术和挑战等》 《腾讯技术分享:微信小程序音视频技术背后的故事》 Q:Denny你好,先简单介绍下自己的经...
- 下一篇
世界领先!详解蚂蚁金服自研数据库OceanBase的高可用及容灾方案
小蚂蚁说: 关于蚂蚁金服自研的金融级分布式关系型数据库OceanBase的故事相信大家已经不再陌生了(新来的同学可以移步《厉害了,蚂蚁金服!创造了中国自己的数据库OceanBase》了解更多~)。其中OceanBase的大规模金融级的高可用及容灾能力深入人心,那么它究竟是怎么做到的呢? 本文用较为详尽的篇幅分别为大家总结和回顾了传统数据库产品常用的高可用及容灾方案,并以此为基础深度解读了基于OceanBase最佳实践的分布式数据库的高可用及容灾方案。一起来学习一下吧~! 此外,欢迎关注蚂蚁金服自研的金融级分布式关系型数据库OceanBase的独家微信公众号,了解更多信息!▼▼ 前言 众所周知,作为生产系统中极为关键的核心软件,数据库产品的高可用性一直是使用者极为关注的功能点。尤其是在金融这样一个特殊的领域里,无论是从监管的要求来看,还是从业
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS8安装Docker,最新的服务器搭配容器使用
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS8编译安装MySQL8.0.19
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- SpringBoot2整合Redis,开启缓存,提高访问速度
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- Hadoop3单机部署,实现最简伪集群
- CentOS7,CentOS8安装Elasticsearch6.8.6
- CentOS6,7,8上安装Nginx,支持https2.0的开启