學習RxJava+Retrofit+OkHttp+MVP的網絡請求使用

公司的大佬用的是這一套,那我這個菜鳥確定要學習使用了。php

我在網上找了不少文章,寫的都很詳細,好比java

https://www.jianshu.com/u/5fd2523645dareact

https://www.jianshu.com/p/193d8c37c73candroid

趁熱打鐵,寫一篇學習筆記,理順思路。git

先把他們都引入
//rxjava
    compile 'io.reactivex.rxjava2:rxjava:2.2.0'
    compile 'io.reactivex.rxjava2:rxandroid:2.0.2'
    compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'

    //retrofit
    compile 'com.squareup.retrofit2:retrofit:2.3.0'

    //okhttp
    compile 'com.squareup.okhttp3:okhttp:3.11.0'
    compile 'com.squareup.okio:okio:1.14.0'
   implementation 'com.squareup.okhttp3:logging-interceptor:3.9.0'
    //gson 
implementation 'com.google.code.gson:gson:2.8.4' implementation 'com.squareup.retrofit2:converter-gson:2.4.0'

 

1、RxJava學習

簡單的說,核心是觀察者模式。那麼這個就頗有意思了,舉個栗子github

 

我訂閱了公衆號以後就能夠去幹其餘的事了,當公衆號有新的文章以後發個消息通知我:有新文章了。這時我再點開去查看。json

RxJava中有這幾種方法api

onNext():一直向我推送文章
onComplete():文章推送完了
onError():推送出現異常,同時終止,再也不有消息發出.
onSubscribe():RxJava 2.0 中新增的,傳遞參數爲Disposable,可用於切斷接收事件服務器

RxJava的鏈式操做網絡

Observable.create(new ObservableOnSubscribe<Integer>() {
            @Override
            public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
                emitter.onNext(1);
                emitter.onNext(2);
                emitter.onNext(3);
                emitter.onComplete();
            }
        })
                .observeOn(AndroidSchedulers.mainThread())//回調在主線程
                .subscribeOn(Schedulers.io())//執行在io線程
                .subscribe(new Observer<Integer>() {
                    @Override
                    public void onSubscribe(Disposable d) {
                        Log.d(TAG, "onSubscribe");
                    }

                    @Override
                    public void onNext(Integer value) {
                        Log.d(TAG, "onNext=" + value);
                    }

                    @Override
                    public void onError(Throwable e) {
                        Log.d(TAG, "onError");
                    }

                    @Override
                    public void onComplete() {
                        Log.d(TAG, "onComplete");
                    }
                });

線程切換流程(observeOn與subscribeOn)

當前爲主(main)線程,訂閱(向上走)

1.開始 subscribe 訂閱

2.經 subscribeOn 將線程切換爲IO線程(Schedulers:線程調度器)

3.經 observeOn 控制數據流的,跳過

4.經 create 在IO線程中執行

到這裏,訂閱完成,開始發射數據。

當前爲IO線程,發射數據(向下走)

1.經 observeOn 將線程切換爲主(main)線程

2.經 subscribeOn 控制訂閱的,跳過

3.經 onNext 在主線程中執行

 整個流程就走完了。

RxJava還有不少操做符,等後面慢慢學習。

2、Retrofit學習

簡單的說,它是網絡適配器,經過OkHttp發送請求

它是將okhttp進行了進一步的封裝翻新

偷張圖哈哈哈 https://www.jianshu.com/p/15edb4de0f62

3、進入正題,打通網絡請求

1.Retrofit封裝

建立Api接口

public interface IApiService {
    @POST("/lay-eggs/androidtest.php")
    Observable<TestBean> getData(@Query("time") String time);
}

 也能夠用@QueryMap 直接整一個集合上去。

TestBean用JsonFormat自動生成

 

建立Retrofit管理類

public class RetrofitManager {
    private static RetrofitManager retrofitManager;
    private Retrofit retrofit;
    private static final String BASE_URL="http://yyyxuan.cn";//根地址
    private IApiService apiService;

    /**
     * 單例模式
     * @return
     */
    public static RetrofitManager getInstance (){
        if (retrofitManager==null){
            synchronized (RetrofitManager.class){
                if (retrofitManager==null){
                    retrofitManager= new RetrofitManager();
                }
            }
        }
        return retrofitManager;
    }

    //構造函數
    private RetrofitManager(){
        initRetrofitManager();
    }

    //建立Retrofit實例
    private void initRetrofitManager() {
        retrofit=new Retrofit.Builder().baseUrl(BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())//對服務器數據進行解析
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())//RxJava適配器
                .build();
        apiService=retrofit.create(IApiService.class);
    }


    public IApiService apiservice(){return apiService;}

}

 2.訂閱關係處理

定義添加刪除訂閱關係的接口

public interface SubscriptionHelper<T> {

    /**
     * 添加
     * @param disposable
     */
    void add(Disposable disposable);

    /**
     * 取消
     * @param disposable
     */
    void cancel(Disposable disposable);

    /**
     * 取消全部
     */
    void cancelAll();
}

建立訂閱關係管理類

public class SubscriptionManager implements SubscriptionHelper<Object> {

    public static SubscriptionManager subscriptionManager;
    private CompositeDisposable mDisposables;//存放disposable容器

    /**
     * 構造函數 new CompositeDisposable對象
     */
    public SubscriptionManager(){
        if (mDisposables==null){
            mDisposables=new CompositeDisposable();
        }
    }

    /**
     * 單例
     * @return
     */
    public static SubscriptionManager getInstance(){
        if (subscriptionManager==null){
            synchronized (SubscriptionManager.class){
                if (subscriptionManager==null){
                    subscriptionManager=new SubscriptionManager();
                }
            }
        }
        return subscriptionManager;
    }

    /**
     * 訂閱事件加入到CompositeDisposable容器中
     * @param disposable 訂閱事件
     */
    @Override
    public void add(Disposable disposable) {
        if(disposable==null) return;
        mDisposables.add(disposable);
    }

    /**
     * 取消訂閱事件
     * @param disposable 訂閱事件
     */
    @Override
    public void cancel(Disposable disposable) {
        if (disposable!=null){
            mDisposables.delete(disposable);
        }
    }

    /**
     * 清除容器全部
     */
    @Override
    public void cancelAll() {
        if (mDisposables!=null){
            mDisposables.clear();
        }
    }
}

 3.異常處理

網上有不少異常處理的類,能夠去搜一下(忘記我看的哪篇文章了)

public class ExceptionHandle {

    private static final int UNAUTHORIZED = 401;
    private static final int FORBIDDEN = 403;
    private static final int NOT_FOUND = 404;
    private static final int REQUEST_TIMEOUT = 408;
    private static final int INTERNAL_SERVER_ERROR = 500;
    private static final int BAD_GATEWAY = 502;
    private static final int SERVICE_UNAVAILABLE = 503;
    private static final int GATEWAY_TIMEOUT = 504;


    public static ResponseException handleException(Throwable e){

        //轉換成ResponseException,根據狀態碼斷定錯誤信息
        ResponseException ex;
        if(e instanceof HttpException){
            HttpException httpException=(HttpException)e;
            /**
             * 傳入狀態碼,根據狀態碼斷定錯誤信息
             */
            ex=new ResponseException(e,ERROR.HTTP_ERROR);
            switch (httpException.code()){
                case UNAUTHORIZED:
                    ex.message="未驗證";
                    break;
                case FORBIDDEN:
                    ex.message="服務禁止訪問";
                    break;
                case NOT_FOUND:
                    ex.message="服務不存在";
                    break;
                case REQUEST_TIMEOUT:
                    ex.message="請求超時";
                    break;
                case GATEWAY_TIMEOUT:
                    ex.message="網關超時";
                    break;
                case INTERNAL_SERVER_ERROR:
                    ex.message="服務器內部錯誤";
                    break;
                case BAD_GATEWAY:

                    break;
                case SERVICE_UNAVAILABLE:
                    break;
                default:
                    ex.message = "網絡錯誤";
                    break;
            }
            return ex;
        }else if(e instanceof JsonParseException
                || e instanceof JSONException
                || e instanceof ParseException){
            ex=new ResponseException(e,ERROR.PARSE_ERROR);
            ex.message="解析錯誤";
            return ex;
        }else if(e instanceof ConnectException){
            ex=new ResponseException(e,ERROR.NETWORD_ERROR);
            ex.message="鏈接失敗";
            return ex;
        }else if(e instanceof javax.net.ssl.SSLHandshakeException){
            ex=new ResponseException(e,ERROR.SSL_ERROR);
            ex.message="證書驗證失敗";
            return ex;
        }else {
            ex=new ResponseException(e,ERROR.UNKNOWN);
            ex.message="未知錯誤";
            return ex;
        }

    }

    /**
     * 約定異常
     */
    public static class ERROR{
        /**
         * 自定義異常
         */
        private static final int UNAUTHORIZED = 401;//請求用戶進行身份驗證
        private static final int UNREQUEST=403;//服務器理解請求客戶端的請求,可是拒絕執行此請求
        private static final int UNFINDSOURCE=404;//服務器沒法根據客戶端的請求找到資源
        private static final int SEVERERROR=500;//服務器內部錯誤,沒法完成請求。
        /**
         * 協議出錯
         */
        public static final int HTTP_ERROR = 1003;
        /**
         * 未知錯誤
         */
        public static final int UNKNOWN = 1000;
        /**
         * 解析錯誤
         */
        public static final int PARSE_ERROR = 1001;
        /**
         * 網絡錯誤
         */
        public static final int NETWORD_ERROR = 1002;
        /**
         * 證書出錯
         */
        public static final int SSL_ERROR = 1005;
    }

    /**
     * 自定義Throwable
     */
    public static class ResponseThrowable extends Exception{
        public int code;
        public String message;
        public ResponseThrowable(Throwable throwable,int code){
            super(throwable);
            this.code=code;
        }
    }

    /**
     * 服務器異常
     */
    public class ServerException extends RuntimeException{
        public int code;
        public String message;
    }

    /**
     * 統一異常類,便於處理
     */
    public static class ResponseException extends Exception{
        public int code;
        public String message;
        public ResponseException (Throwable throwable,int code){
            super(throwable);
            this.code=code;
        }
    }

}

4.Observer封裝

上面講到了四個方法以及他們的做用,這裏簡單的封裝一下

public abstract class Observer<T> implements io.reactivex.Observer<T> {
    @Override
    public void onSubscribe(Disposable d) {
        OnDisposable(d);
    }

    @Override
    public void onNext(T t) {
        OnSuccess(t);
    }

    @Override
    public void onError(Throwable e) {
        OnFail(ExceptionHandle.handleException(e));
    }

    @Override
    public void onComplete() {
        OnCompleted();
    }


    protected abstract void OnDisposable(Disposable d);

    protected abstract void OnSuccess(T t);

    protected abstract void OnFail(ExceptionHandle.ResponseException e);

    protected abstract void OnCompleted();
}

5.MVP搭建

 

網上找了很詳細的圖解

View:負責繪製UI元素、與用戶進行交互。

Model:負責存儲、檢索、操縱數據。

Presenter:做爲View與Model交互的中間紐帶,處理與用戶交互的負責邏輯。

M與V層須要P層來進行通訊。

Model層

添加訂閱關係,進行網絡請求。

public class TestModel {
    public void getTestInfo(String time, Observer<TestBean> observer){
        RetrofitManager.getInstance().apiservice().getData(time)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribeOn(Schedulers.io())
                .subscribe(observer);
    }
}

各類基類的封裝

P層 用來綁定和解除與v層關係

public class BasePresenter<V extends BaseView> {
    public V view;

    /**
     * 添加view
     * @param v
     */
    public void addView(V v){
        this.view=v;
    }

    /**
     * 解除
     */
    public  void breakView(){
        if (view!=null){
            view=null;
        }
    }
}

V層 定義回調功能,可根據不一樣需求更改

public interface BaseView {

    /**
     * 成功回調
     * @param object
     */
    void onSuccess(Object object);

    /**
     * 失敗回調
     * @param t 異常
     */
    void onFail(ExceptionHandle.ResponseException t);

    /**
     * 發射結束
     */
    void onCompleted();
}

activity基類

public abstract class BaseActivity<P extends BasePresenter> extends AppCompatActivity implements BaseView {
    public Context context;
    protected P presenter;

    //獲取P層
    protected abstract P createPresenter();
    //獲取是哪一個activity
    protected abstract int getLayoutId();

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        context=this;
        setContentView(getLayoutId());
        presenter=createPresenter();
        presenter.addView(this);//綁定view
        initView();
        initData();
    }

    public void initData(){

    };

    public void initView(){

    };

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (presenter != null) {
            presenter.breakView();
            SubscriptionManager.getInstance().cancelAll();
        }
    }
}

真正的Presenter

public class TestPresenter extends BasePresenter<BaseView> {
    private TestModel testModel;
    /**
     * 綁定M層
     */
    public TestPresenter (){
        testModel=new TestModel();
    }

    public void test(String time){
        //網絡請求,建立觀察者
        testModel.getTestInfo(time, new Observer<TestBean>() {
            @Override
            protected void OnDisposable(Disposable d) {
                SubscriptionManager.getInstance().add(d);
            }

            @Override
            protected void OnSuccess(TestBean testBean) {
                view.onSuccess(testBean);
            }

            @Override
            protected void OnFail(ExceptionHandle.ResponseException e) {
                view.onFail(e);
            }

            @Override
            protected void OnCompleted() {
                view.onCompleted();
            }
        });
    }
}

 

真正的Activity

public class MainActivity extends BaseActivity<TestPresenter> implements BaseView {
    String TAG="aaa";
    TextView textView;
    Button button;

    /**
     * 綁定p層
     * @return
     */
    @Override
    protected TestPresenter createPresenter() {
        return new TestPresenter();
    }

    /**
     * 加載當前activity
     * @return
     */
    @Override
    protected int getLayoutId() {
        return R.layout.activity_main;
    }

    /**
     * 成功回調
     * @param object 
     */
    @Override
    public void onSuccess(Object object) {
        Log.d(TAG, "onSuccess: "+beanToJson(object));
        TestBean testBean= (TestBean) object;
        textView.setText(testBean.getData().getContent());
    }

    /**
     * 失敗回調
     * @param t 異常
     */
    @Override
    public void onFail(ExceptionHandle.ResponseException t) {
        Log.d(TAG, t.message.toString());
    }

    @Override
    public void onCompleted() {

    }

    public String beanToJson(Object bean) {
        Gson gson = new Gson();
        String jsonStr = gson.toJson(bean);
        return jsonStr;
    }

    /**
     * 初始化界面
     */
    @Override
    public void initView() {
        super.initView();
        textView=findViewById(R.id.mtv);
        button=findViewById(R.id.mbtn);
    }

    /**
     * 初始化數據
     */
    @Override
    public void initData() {
        super.initData();
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                presenter.test("123");
            }
        });
    }
}

 別忘了最重要的網絡權限(在AndroidManifest.xml)

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

 github:https://github.com/steffenx/RxJava-Retrofit-mvp

6.最後

寫下這篇博客是幫助我學習,知識梳理,加深印象。之後也能翻出來看看對吧(狗頭)

相關文章
相關標籤/搜索