查看: 2631|回复: 0

[Android教程] Retrofit+MVP框架封装记录篇

发表于 2018-1-11 08:00:00

当下最流行的网络请求组合,retrofit2+okhttp+rxjava+mvp

这里是封装记录篇

首先分模块,比如登录

先来说封装后的使用

  1. package com.fragmentapp.login.presenter;
  2. import android.util.Log;
  3. import com.fragmentapp.base.BasePresenter;
  4. import com.fragmentapp.http.BaseObserver;
  5. import com.fragmentapp.http.BaseResponses;
  6. import com.fragmentapp.login.bean.LoginDataBean;
  7. import com.fragmentapp.login.imple.ILoginModel;
  8. import com.fragmentapp.login.imple.ILoginView;
  9. import com.fragmentapp.login.model.LoginModel;
  10. /**
  11. * Created by liuzhen on 2017/11/3.
  12. */
  13. public class LoginPresenter extends BasePresenter {
  14. private ILoginView view;
  15. private ILoginModel model;
  16. public LoginPresenter(ILoginView view){
  17. this.view = view;
  18. model = new LoginModel();
  19. }
  20. public void login(String username,String pwd){
  21. model.login(observer,username,pwd);
  22. }
  23. BaseObserver<BaseResponses<LoginDataBean>> observer = new BaseObserver<BaseResponses<LoginDataBean>>(){
  24. @Override
  25. public void onNextResponse(BaseResponses<LoginDataBean> loginDataBean) {
  26. Log.e("token",loginDataBean.getData().getHCACCESSTOKEN()+"");
  27. view.success(loginDataBean.getData());
  28. }
  29. @Override
  30. public void onErrorResponse(BaseResponses<LoginDataBean> loginDataBean) {
  31. view.error();
  32. }
  33. @Override
  34. public void onNetWorkError(String val) {
  35. view.error();
  36. }
  37. };
  38. }
复制代码
Presenter

通过p层的接口来交互,model去访问网络请求,然后返回结果回调返回到view层去刷新

这里自定义了一个base的obsever类,避免多次的传递接口

model则负责调用网络请求了

  1. package com.fragmentapp.login.model;
  2. import com.fragmentapp.http.BaseObserver;
  3. import com.fragmentapp.http.BaseResponses;
  4. import com.fragmentapp.http.RetrofitHelper;
  5. import com.fragmentapp.login.bean.LoginDataBean;
  6. import com.fragmentapp.login.imple.ILoginModel;
  7. import java.util.HashMap;
  8. import java.util.Map;
  9. import io.reactivex.android.schedulers.AndroidSchedulers;
  10. import io.reactivex.schedulers.Schedulers;
  11. /**
  12. * Created by liuzhen on 2017/11/7.
  13. */
  14. public class LoginModel implements ILoginModel {
  15. @Override
  16. public void login(final BaseObserver<BaseResponses<LoginDataBean>> observer,String username,String pwd) {
  17. Map<String, String> map = new HashMap<>();
  18. map.put("account[username]", username);
  19. map.put("account[password]", pwd);
  20. RetrofitHelper.getInstance().getService()
  21. .login(map)
  22. .subscribeOn(Schedulers.io())
  23. .observeOn(AndroidSchedulers.mainThread())
  24. .subscribe(observer);
  25. }
  26. }
复制代码
View Code

view层的回调也只有两个接口,可以根据自己的需求添加

  1. package com.fragmentapp.login.imple;
  2. import com.fragmentapp.login.bean.LoginDataBean;
  3. /**
  4. * Created by liuzhen on 2017/11/6.
  5. */
  6. public interface ILoginView {
  7. void success(LoginDataBean dataBean);
  8. void error();
  9. }
复制代码
View Code

访问网络后直接在activity里处理回调的结果刷新界面等

这里的retrofit的访问url是用的添加头部tag来达到动态访问替换baseurl的目的

  1. package com.fragmentapp.http;
  2. import android.util.Log;
  3. import com.fragmentapp.BuildConfig;
  4. import com.google.gson.Gson;
  5. import com.google.gson.GsonBuilder;
  6. import java.io.IOException;
  7. import java.util.List;
  8. import java.util.concurrent.TimeUnit;
  9. import okhttp3.HttpUrl;
  10. import okhttp3.Interceptor;
  11. import okhttp3.OkHttpClient;
  12. import okhttp3.Request;
  13. import okhttp3.Response;
  14. import okhttp3.logging.HttpLoggingInterceptor;
  15. import retrofit2.Retrofit;
  16. import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
  17. import retrofit2.converter.gson.GsonConverterFactory;
  18. /**
  19. * Created by liuzhen on 2017/11/3.
  20. */
  21. public class RetrofitHelper {
  22. private static final String BASE_URL_USER = "http://testapi.hanmaker.com";
  23. private static final String BASE_URL_PAY = "https://www.222.com/";
  24. private static final long TIME_OUT = 5000;
  25. private RetrofitHelper(){}
  26. private static class SingleHolder {
  27. private static final RetrofitHelper INSTANCE = new RetrofitHelper();
  28. }
  29. public static final RetrofitHelper getInstance() {
  30. return SingleHolder.INSTANCE;
  31. }
  32. private static final long DEFAULT_TIMEOUT = 15L;
  33. final static Gson gson = new GsonBuilder()
  34. .setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
  35. .serializeNulls()// 调用serializeNulls方法,改变gson对象的默认行为,null值将被输出
  36. .create();
  37. //addInterceptor:设置应用拦截器,可用于设置公共参数,头信息,日志拦截等
  38. //addNetworkInterceptor:网络拦截器,可以用于重试或重写
  39. //setLevel NONE(不记录) BASIC(请求/响应行) HEADER(请求/响应行 + 头) BODY(请求/响应行 + 头 + 体)
  40. //cookieJar:保持在同一个会话里面
  41. //TimeUnit.SECONDS秒做单位
  42. private static OkHttpClient okHttpClient = new OkHttpClient.Builder()
  43. .writeTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
  44. .connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
  45. .readTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
  46. .addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
  47. .retryOnConnectionFailure(true)//错误重联
  48. .addInterceptor(new Interceptor() {
  49. @Override
  50. public Response intercept(Chain chain) throws IOException {
  51. //获取request
  52. Request request = chain.request();
  53. if (BuildConfig.DEBUG) {
  54. // Log.e("request",request.toString());
  55. }
  56. //获取request的创建者builder
  57. Request.Builder builder = request.newBuilder();
  58. //从request中获取headers,通过给定的键url_name
  59. List<String> headerValues = request.headers("url_name");
  60. if (headerValues != null && headerValues.size() > 0) {
  61. //如果有这个header,先将配置的header删除,因此header仅用作app和okhttp之间使用
  62. builder.removeHeader("url_name");
  63. //匹配获得新的BaseUrl
  64. String headerValue = headerValues.get(0);
  65. HttpUrl newBaseUrl = null;
  66. if ("user".equals(headerValue)) {
  67. newBaseUrl = HttpUrl.parse(BASE_URL_USER);
  68. } else if ("pay".equals(headerValue)) {
  69. newBaseUrl = HttpUrl.parse(BASE_URL_PAY);
  70. } else{
  71. newBaseUrl = HttpUrl.parse(BASE_URL_USER);
  72. }
  73. //从request中获取原有的HttpUrl实例oldHttpUrl
  74. HttpUrl oldHttpUrl = request.url();
  75. //重建新的HttpUrl,修改需要修改的url部分
  76. HttpUrl newFullUrl = oldHttpUrl
  77. .newBuilder()
  78. .scheme(newBaseUrl.scheme())//设置网络协议
  79. .host(newBaseUrl.host())//更换主机名
  80. .port(newBaseUrl.port())//更换端口
  81. .build();
  82. //重建这个request,通过builder.url(newFullUrl).build();
  83. //然后返回一个response至此结束修改
  84. return chain.proceed(builder.url(newFullUrl).build());
  85. } else {
  86. return chain.proceed(request);
  87. }
  88. }
  89. })
  90. .build();
  91. private static Retrofit retrofit = null;
  92. private static <T> T createApi(Class<T> clazz) {
  93. retrofit = new Retrofit.Builder()
  94. .baseUrl(BASE_URL_USER)
  95. .client(okHttpClient)
  96. .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
  97. .addConverterFactory(GsonConverterFactory.create(gson))
  98. .build();
  99. return retrofit.create(clazz);
  100. }
  101. private RetrofitService service = null;
  102. public RetrofitService getService(){
  103. if (service == null)
  104. service = createApi(RetrofitService.class);
  105. return service;
  106. }
  107. }
复制代码
View Code

然后接口参数采用map的方式添加,个人感觉一个个分开来跟烦,每次都得改service类

然后observable套用了一层类型,这里主要是后台数据格式吭,可以去掉

  1. package com.fragmentapp.http;
  2. /**
  3. * Created by liuzhen on 2017/11/3.
  4. */
  5. public class BaseResponses<T> {
  6. private String info;
  7. private int status;
  8. private T data;
  9. public String getInfo() {
  10. return info;
  11. }
  12. public void setInfo(String info) {
  13. this.info = info;
  14. }
  15. public int getStatus() {
  16. return status;
  17. }
  18. public void setStatus(int status) {
  19. this.status = status;
  20. }
  21. public T getData() {
  22. return data;
  23. }
  24. public void setData(T data) {
  25. this.data = data;
  26. }
  27. }
复制代码
View Code

然后是base的observer类,在里面根据自己的业务去回调自定义的接口,这样就不用每次重载这么多的方法了

  1. package com.fragmentapp.http;
  2. import android.os.Looper;
  3. import android.util.Log;
  4. import io.reactivex.Observer;
  5. import io.reactivex.disposables.Disposable;
  6. /**
  7. * Created by liuzhen on 2017/11/3.
  8. */
  9. public abstract class BaseObserver<T extends BaseResponses> implements Observer<T> {
  10. String TAG = getClass().getSimpleName();
  11. @Override
  12. public void onSubscribe(Disposable d) {
  13. Log.e(TAG, "onSubscribe");
  14. }
  15. @Override
  16. public void onNext(T t) {
  17. Log.e(TAG, "onNext"+t);
  18. if (t.getStatus() == 200) {
  19. onNextResponse(t);
  20. } else {
  21. Log.e(TAG, "ErrorStatus:" + t.getStatus() + "ErrorInfo" + t.getInfo());
  22. onErrorResponse(t);
  23. }
  24. }
  25. @Override
  26. public void onError(Throwable e) {
  27. Log.e(TAG, "onError" + e.toString());
  28. onNetWorkError("onError 网络超时,请重新尝试--"+e.getMessage());
  29. if (Looper.myLooper() == null) {
  30. Looper.prepare();
  31. Log.e(TAG,"onError 网络超时,请重新尝试");
  32. Looper.loop();
  33. }
  34. }
  35. @Override
  36. public void onComplete() {
  37. Log.e(TAG, "onComplete");
  38. }
  39. /**返回成功*/
  40. public abstract void onNextResponse(T t);
  41. /**接口失败信息*/
  42. public abstract void onErrorResponse(T t);
  43. /**网络错误*/
  44. public abstract void onNetWorkError(String val);
  45. }
复制代码
View Code

这个没啥好说的了

GitHub:https://github.com/1024477951/FragmentApp



回复

使用道具 举报