okhttp3+retrofit2+rxjava+MMVP以注册为例概述一个网络请求的完整流程

注:这里以注册为例概述网络请求的完整流程,是指以我的方式、流程进行的请求,不同的开发者有不同的思路和流程

一.引入包(如果有哪些找不到文件的,那就是缺包了)、网络权限

api com.squareup.retrofit2:adapter-rxjava:2.5.0
api com.squareup.retrofit2:converter-gson:2.5.0
api io.reactivex.rxjava2:rxjava:2.0.1
api android.arch.lifecycle:viewmodel:1.1.1
api android.arch.lifecycle:livedata:1.1.1

<uses-permission android:name="android.permission.INTERNET"/>

二.注册布局、RegisterActivity准备好,其中需要如下代码:

public RegisterViewModel registerViewModel;//申明

registerViewModel = ViewModelProviders.of(this).get(RegisterViewModel.class);//在onCreate方法

registerViewModel.register(****);//点击注册按钮后校验输入符合要求后调用

/*接收网络请求后的结果
register、0、1、2建议建一个常量类,这样子方便对应(效果图中有) 
 要对应RegisterViewModel 中返回的
0、2若是没有特殊处理可以合并,因只处理成功的逻辑,其它全部当失败Toast显示
*/
private void initEven() {
        LiveDataBus.get().with("register", MessageModel.class).observe(this, messageModel -> {
            switch (messageModel.what) {

                //网络错误
                case 0:
                    //处理逻辑
                   break;
                //成功
                case 1:
                   //获取registerViewModel 传来的数据,类型跟传的一致
                   RegisterResponse response= (RegisterResponse) messageModel.obj;             
                    break;
                //失败
                case 2:
                //处理逻辑
                    break;
            }
        });

    }

三.RegisterViewModel用到的一层一层写下去

3.1 RegisterViewModel继承ViewModel,RegisterResponse是后台返回成功时的模型

public class RegisterViewModel extends ViewModel {
    private WebRepository webRepository;

//register、0、1、2 activity接收返回的数据要对应这里的
 public void register(***) {
        webRepository = new WebRepository(application);
     
        Map<String, String> registerMap = new HashMap<>();
        registerMap.put("***", ***);  //把参数全部加入到registerMap 

        //后面调用的方法都要跟BaseCallBean<RegisterResponse>一样
        Observable<BaseCallBean<RegisterResponse>> observable = webRepository.register(registerMap);
        observable.subscribeOn(Schedulers.io())//请求数据的事件发生在io线程
                .observeOn(AndroidSchedulers.mainThread())//请求完成后在主线程更显UI
                .subscribe(new Observer<BaseCallBean<RegisterResponse>>() {
                    @Override
                    public void onCompleted() {
                    }

                    @Override
                    public void onError(Throwable e) {
                        sendLiveDataBus(0,e.toString);
                    }

                    @Override
                    public void onNext(BaseCallBean<RegisterResponse> register) {
                        if (10000 ==register.getStatus() && null != register.getData()) {//成功,跟后台约定好,返回10000是成功
                        sendLiveDataBus(1,register.getData())
                        } else {//请求异常的:用户已存在、验证失败……
                         sendLiveDataBus(2,register.getMsg())
                        }
                    }
                });
    }

    private void sendLiveDataBus(int what, Object data) {
        new Handler(application.getMainLooper()).post(new Runnable() {
            @Override
            public void run() {
                // 在这里执行你要想的操作 比如直接在这里更新ui或者调用回调在 在回调中更新ui
                LiveDataBus.get().with("register").postValue(new MessageModel(what, data));
            }
        });
    }
}
public class BaseCallBean<T> {
    public int status;
    public String msg;
    public T data;

    @Override
    public String toString() {
        return "BaseCallBean{" +
                "status=" + status +
                ", msg='" + msg + '\'' +
                ", data=" + data +
                '}';
    }
    public int getStatus() {
        return status;
    }
    public void setStatus(int status) {
        this.status = status;
    }
    public String getMsg() {
        return msg;
    }
    public void setMsg(String msg) {
        this.msg = msg;
    }
    public T getData() {
        return data;
    }
    public void setData(T data) {
        this.data = data;
    }
}

3.2 WebRepository数据代理

public class WebRepository {
     private final Webservice webservice;//服务器
     private BaseHeader header;//封装的请求头
    
     public WebRepository(final Application application) {
        BaseHeader header = Header();
        this.header = header;
        String baseUrl = ****;//基础的url,会拼接到后面的注解url形成完整的url进行网络请求
        webservice = new Webservice(baseURL, header);
    }

      //BaseCallBean<RegisterResponse>跟调用register方法的一样
     public Observable<BaseCallBean<RegisterResponse>> register(Map<String, String> registerMap) {
        return webservice.register(registerMap);
    }

 public BaseHeader Header() {//赋值请求头,每次请求都要赋值,因登录前后的请求头不一样
        BaseHeader baseHeader = new BaseHeader();      
        baseHeader.setUserId(***);       
        return baseHeader;
    }
}

3.3.1  Webservice服务器

public class Webservice {

  private RetrofitHelper helper;

  public Webservice(String baseURL,BaseHeader header) {
        helper =  RetrofitHelper.getInstance(baseURL,header);
    }

  public Observable<BaseCallBean<RegisterResponse>> register(Map<String,String> registerMap) {
        return helper.getServer().register(registerMap);
    }
} 

3.3.2 BaseHeader请求头(是一个类)

public class BaseHeader {
    private String ***;
    public String get***() {
        return ***;
    }
    public void set***(String ***) {
        ***= ***;
    }
    public Map<String, String> toMap() {//这个方法是Retrofit获取请求头时调用的
        Map<String, String> headers = new HashMap<>();   
        if (null != get***()) {
            headers.put("***", get***());
        }    
        return headers;
    }
}

3.3.4 RetrofitHelper

public class RetrofitHelper {

    public static RetrofitHelper getInstance(String baseURL, BaseHeader header) {
        return new RetrofitHelper(baseURL, header);
    }

  private RetrofitHelper(String baseURL, BaseHeader header) {
        this.baseURL = baseURL;
        this.header = header;
        init();
    }
    private void init() {
        //OkHttpClient.Builder创建OkHttpClient,用它来对OkHttpClient进行一些设置
         OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder();     

        //不设置一些改变的属性,则会默认,eg:连接超时
        OkHttpClient client = clientBuilder
                .connectTimeout(10, TimeUnit.SECONDS)//连接超时设置
                .readTimeout(20, TimeUnit.SECONDS)//读超时设置
                .writeTimeout(20, TimeUnit.SECONDS)//写超时设置
                .addInterceptor(chain -> {//自定义拦截器,为请求添加统一的请求头……
                    Request.Builder builder = chain.request().newBuilder();
                    if (null != header) {
                        Map<String, String> headersMap = header.toMap();//将请求头数据写入
                        for (Map.Entry<String, String> entry : headersMap.entrySet()) {
                            if (null != entry.getValue()) {
                                builder.addHeader(entry.getKey(), entry.getValue());//将数据添加到请求头中
                            }
                        }
                    }
                    Request request = builder.build();
                    return chain.proceed(request);
                })
                .build();//构建client

        mRetrofit = new Retrofit.Builder()
                .baseUrl(baseURL)//请求的基础Url,后面会拼接上注解的url形成完整的URL
                .client(client)//设置自定义的OkHttpClient
                .addConverterFactory(GsonConverterFactory.create(new GsonBuilder().create()))//支持Gson解析
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())//支持RxJava
                .build();
    }

 public UserService getServer() {
        return mRetrofit.create(UserService.class);//创建 网络请求接口 的实例
    }

3.3.5服务UserService

  • 方法注解:@GET、@POST、@PUT、@DELETE、@PATH、@HEAD、@OPTIONS、@HTTP
  • 标记注解:@FormUrlEncoded、@Multipart、@Streaming
  • 参数注解:@Query、@QueryMap、@Body、@Field、@FieldMap、@Part、@PartMap、@Path、@Header、@Headers、@Url
public interface UserService {
    @FormUrlEncoded //API规定采用请求格式x-www-form-urlencoded,即表单形式
    @POST("api/AppLogin/Register")
  //WebRepository中的baseUrl拼接上api/AppLogin/Register形成完整的请求url,
  //记得baseUrl以/结束(因前面的没有以/开始)
  //@FieldMap向后台提交字段,所有的字段都在里面;后台返回的要符合json格式,不然会报转换失败错误
    Observable<BaseCallBean<RegisterResponse>> register(@FieldMap  Map<String,String> registerMap);
}

3.4 LiveDataBus

public final class LiveDataBus {
    private final Map<String, BusMutableLiveData<Object>> bus;
    private LiveDataBus() {
        bus = new HashMap<>();
    }
    private static class SingletonHolder {
        private static final LiveDataBus DEFAULT_BUS = new LiveDataBus();
    }
    public static LiveDataBus get() {
        return SingletonHolder.DEFAULT_BUS;
    }
    public synchronized <T> Observable<T> with(String key, Class<T> type) {
        if (!bus.containsKey(key)) {
            bus.put(key, new BusMutableLiveData<>());
        }
        return (Observable<T>) bus.get(key);
    }
    public Observable<Object> with(String key) {
        return with(key, Object.class);
    }
    public interface Observable<T> {
        void setValue(T value);
        void postValue(T value);
        void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer);
    }

    private static class BusMutableLiveData<T> extends MutableLiveData<T> implements Observable<T> {
        private class PostValueTask implements Runnable {
            private Object newValue;
            public PostValueTask(@NonNull Object newValue) {
                this.newValue = newValue;
            }
            @Override
            public void run() {
                setValue((T) newValue);
            }
        }

        private Map<Observer, Observer> observerMap = new HashMap<>();
        private Handler mainHandler = new Handler(Looper.getMainLooper());
        @Override
        public void postValue(T value) {
            mainHandler.post(new PostValueTask(value));
        }
        @Override
        public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) {
            super.observe(owner, observer);
            try {
                hook(observer);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        @Override
        public void observeForever(@NonNull Observer<T> observer) {
            if (!observerMap.containsKey(observer)) {
                observerMap.put(observer, new ObserverWrapper(observer));
            }
            super.observeForever(observerMap.get(observer));
        }

        @Override
        public void removeObserver(@NonNull Observer<T> observer) {
            Observer realObserver = null;
            if (observerMap.containsKey(observer)) {
                realObserver = observerMap.remove(observer);
            } else {
                realObserver = observer;
            }
            super.removeObserver(realObserver);
        }
        private void hook(@NonNull Observer<T> observer) throws Exception {
            //get wrapper's version
            Class<LiveData> classLiveData = LiveData.class;
            Field fieldObservers = classLiveData.getDeclaredField("mObservers");
            fieldObservers.setAccessible(true);
            Object objectObservers = fieldObservers.get(this);
            Class<?> classObservers = objectObservers.getClass();
            Method methodGet = classObservers.getDeclaredMethod("get", Object.class);
            methodGet.setAccessible(true);
            Object objectWrapperEntry = methodGet.invoke(objectObservers, observer);
            Object objectWrapper = null;
            if (objectWrapperEntry instanceof Map.Entry) {
                objectWrapper = ((Map.Entry) objectWrapperEntry).getValue();
            }
            if (objectWrapper == null) {
                throw new NullPointerException("Wrapper can not be bull!");
            }
            Class<?> classObserverWrapper = objectWrapper.getClass().getSuperclass();
            Field fieldLastVersion = classObserverWrapper.getDeclaredField("mLastVersion");
            fieldLastVersion.setAccessible(true);
            //get livedata's version
            Field fieldVersion = classLiveData.getDeclaredField("mVersion");
            fieldVersion.setAccessible(true);
            Object objectVersion = fieldVersion.get(this);
            //set wrapper's version
            fieldLastVersion.set(objectWrapper, objectVersion);
        }
    }
    private static class ObserverWrapper<T> implements Observer<T> {
        private Observer<T> observer;
        public ObserverWrapper(Observer<T> observer) {
            this.observer = observer;
        }
        @Override
        public void onChanged(@Nullable T t) {
            if (observer != null) {
                if (isCallOnObserve()) {
                    return;
                }
                observer.onChanged(t);
            }
        }
        private boolean isCallOnObserve() {
            StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
            if (stackTrace != null && stackTrace.length > 0) {
                for (StackTraceElement element : stackTrace) {
                    if ("android.arch.lifecycle.LiveData".equals(element.getClassName()) &&
                            "observeForever".equals(element.getMethodName())) {
                        return true;
                    }
                }
            }
            return false;
        }
    }
}

3.5效果图(前面以注册为例,这里是截图创建密码的,都是一样的)

注:整个项目中不要大量使用 LiveDataBus,不然会产生很多的常量声明(是项目逐渐变大后发现的,每一对传送、接收(eg:register的viewmodel、activity中的要一致,login中要另外声明不一样的……如下图)),如果可以用回调的方式接收数据的就用回调的方式。

如有更好的建议、方法,请评论区指教,谢谢! 

发布了63 篇原创文章 · 获赞 11 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/weixin_40420578/article/details/103600217