Retrofit的簡單封裝

總結一下自己對Retrofit的使用,使用辦法延續之前封裝Volley的使用方法,不好的地方希望看到各位能給予寶貴的建議,謝謝

首先來看看Retrofit的使用

網絡上有很多的關於Retrofit的使用的文章,我學習Retrofit使用也是通過網上查找文章
我所參考的原文地址爲:http://www.tuicool.com/articles/AveimyQ
1、添加依賴或者導入Jar包
依賴的添加:
compile 'com.squareup.retrofit2:retrofit:2.1.0'  
你也可以導入最新的依賴版本
至於Jar,之後我會隨Demo一起上傳
2、創建業務請求接口
public interface MyRetrofitService {
    //最簡單的Get請求,參數以map形式傳遞
    @GET()
    Call<BookSearchResponse> getService (@Url String url,@QueryMap Map<String,String> Para);
}
3、創建一個Retrofit實例
Retrofit retrofit = new Retrofit.Builder()
                .addConverterFactory(GsonConverterFactory.create())
                .baseUrl(IP)
                .build();
4、調用請求方法,得到Call的實例,並完成異步請求
BlueService service = retrofit.create(BlueService.class);
Call<BookSearchResponse> call = mBlueService.getSearchBooks("小王子", "", 0, 3);
call.enqueue(new Callback<BookSearchResponse>() {
@Override
public void onResponse(Call<BookSearchResponse> call, Response<BookSearchResponse> response) {
	asyncText.setText("異步請求結果: " + response.body().books.get(0).altTitle);
}
@Override
public void onFailure(Call<BookSearchResponse> call, Throwable t) {
}
});
以上4個步驟,就可以完成的Retrofit的基本的網絡請求。
但是總感覺使用起來不方便,而且回調裏返回BooSearchResponse這個bean對象好像只能應對與簡單的Json格式,當公司的接口返回的Json格式複雜的時候,我還是希望將Json的解析與網絡的請求返回的數據進行分離,所以重寫重寫Retrofit的解析器使返回對象爲String類型
新建StringConverterFactory類,代碼如下:
public class StringConverterFactory extends Converter.Factory {

    public static StringConverterFactory create() {
        return new StringConverterFactory();
    }

    private StringConverterFactory() {

    }

    @Override
    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
                                                            Retrofit retrofit) {
        return new StringResponseBodyConverter();
    }

    @Override
    public Converter<?, RequestBody> requestBodyConverter(Type type,
                                                          Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
        return new StringRequestBodyConverter();
    }
}
之後還要實現Resuest請求體類和Response響應體類,分別爲StringRequestBodyConverter和StringResponseBodyConverter代碼如下:
StringRequestBodyConverter
public class StringRequestBodyConverter implements Converter<String, RequestBody> {
    private static final MediaType MEDIA_TYPE = MediaType.parse("application/json; charset=UTF-8");
    private static final Charset UTF_8 = Charset.forName("UTF-8");

    StringRequestBodyConverter() {
    }

    @Override public RequestBody convert(String value) throws IOException {
        Buffer buffer = new Buffer();
        Writer writer = new OutputStreamWriter(buffer.outputStream(), UTF_8);
        writer.write(value);
        writer.close();
        return RequestBody.create(MEDIA_TYPE, buffer.readByteString());
    }
}
StringResponseBodyConverter
public class StringResponseBodyConverter  implements Converter<ResponseBody, String> {
    @Override
    public String convert(ResponseBody value) throws IOException {
        try {
            return value.string();
        } finally {
            value.close();
        }
    }
}
之後在創建業務請求接口的時候就可以這樣
public interface MyRetrofitService {
    //最簡單的Get請求,參數以map形式傳遞
    @GET()
    Call<String> getService (@Url String url,@QueryMap Map<String,String> Para);
}
在創建Retrofit的實例的時候就可以這樣使用
Retrofit retrofit = new Retrofit.Builder()
                .addConverterFactory(StringConverterFactory.create())
                .baseUrl(IP)
                .build();
而在異步請求的回調方法得到的body()也將是一個String類型,再寫一個回調接口,將Json的解析單獨封裝,並在其他部分進行解析

封裝的Retrofit方法包括簡單的Get請求,簡單的Post請求,使用Post請求的文件上傳,圖片按照尺寸壓縮的上傳,使用Get的文件下載,以及圖片的網絡加載(由於自己的能力有限,封裝的圖片加載的方法個人感覺不好用,所有又加入了ImageLoader用於圖片的網絡加載)
創建業務請求的整體接口如下:
public interface MyRetrofitService {
    //最簡單的Get請求,參數以map形式傳遞
    @GET()
    Call<String> getService (@Url String url,@QueryMap Map<String,String> Para);

    @GET()
    Call<String> getService (@Url String url);
    //下載文件(包含下載進度)
    @GET()
    Call<ResponseBody> getFileService(@Url String url);

    @GET()
    Call<ResponseBody> getFileService(@Url String url,@QueryMap Map<String,String> Para);

    //Post請求 以表單的形式
    @FormUrlEncoded
    @POST()
    Call<String> postService(@Url String url,@FieldMap Map<String,String> Para);

    //上傳文件(可以攜帶參數)用@Part
    //如下所示
    @Multipart
    @POST()//多文件上傳
    Call<String> putService(@Url String url,@PartMap Map<String, MultipartBody.Part> Filemap);

    @Multipart
    @POST()//多文件上傳,攜帶參數(在使用的時候根據攜帶的參數而定)
    Call<String> putService(@Url String url,@PartMap Map<String, MultipartBody.Part> Filemap,@Part("name") RequestBody description);

    @Multipart
    @POST()//單文件上傳
    Call<String> putService(@Url String url,@Part MultipartBody.Part File);

    @Multipart
    @POST()//單文件上傳,攜帶參數(在使用的時候根據攜帶的參數而定)
    Call<String> putService(@Url String url,@Part  MultipartBody.Part File,@Part("name") RequestBody description);
}
整體的使用方法都是大同小異的,基本都是上面的幾步。

但是現在又有一個問題,Retrofit沒有提供上傳和下載的進度回調,這個時候就感覺*****(和諧)。在網上又找了好長的時間,終於找到了思路,自己重寫RequestBody和ResponseBody在其中加入進度的回調
先定義進度回調接口ProgressListener如下:
public interface ProgressListener {

    void update(long bytesRead, long contentLength, boolean done);
}
之後重寫RequestBody和ResponseBody 如下:
public class ProgressResponseBody extends ResponseBody {
    private final ResponseBody responseBody;
    private final ProgressListener progressListener;
    private BufferedSource bufferedSource;

    public ProgressResponseBody(ResponseBody responseBody, ProgressListener progressListener) {
        this.responseBody = responseBody;
        this.progressListener = progressListener;
    }

    @Override
    public MediaType contentType() {
        return responseBody.contentType();
    }


    @Override
    public long contentLength() {
        return responseBody.contentLength();
    }

    @Override
    public BufferedSource source() {
        if (bufferedSource == null) {
            bufferedSource = Okio.buffer(source(responseBody.source()));
        }
        return bufferedSource;
    }

    private Source source(Source source) {
        return new ForwardingSource(source) {
            long totalBytesRead = 0L;
            long bytesWritten = responseBody.contentLength();
            @Override
            public long read(Buffer sink, long byteCount) throws IOException {
                long bytesRead = super.read(sink, byteCount);
                totalBytesRead += bytesRead != -1 ? bytesRead : 0;
                progressListener.update(totalBytesRead,bytesWritten , bytesWritten == totalBytesRead);
                return bytesRead;
            }
        };
    }
}
RequestBody:
public class ProgressRequestBody extends RequestBody {

    //實際的請求體
    private RequestBody body;
    //進度回調接口
    private ProgressListener progressListener;
    //包裝完成的BufferedSink
    private BufferedSink bufferedSink;

    public ProgressRequestBody(RequestBody body,ProgressListener progressListener){
        this.body = body;
        this.progressListener = progressListener;
    }

    /**
     * 重寫調用實際響應體的contentType
     * @return
     */
    @Override
    public MediaType contentType() {
        return body.contentType();
    }

    @Override
    public void writeTo(BufferedSink sink) throws IOException {
        if (bufferedSink == null) {
            //包裝
            bufferedSink = Okio.buffer(sink(sink));
        }
        //寫入
        body.writeTo(bufferedSink);
        //必須調用flush,否則最後一部分數據可能不會被寫入
        bufferedSink.flush();
    }

    /**
     * 寫入,回調進度接口
     * @param sink
     * @return
     */
    private Sink sink(Sink sink){
        return new ForwardingSink(sink) {
            //當前寫入字節數
            long bytesWritten = 0L;
            //總字節長度,避免多次調用contentLength()方法
            long contentLength = 0L;
            @Override
            public void write(Buffer source, long byteCount) throws IOException {
                super.write(source, byteCount);
                if (contentLength == 0) {
                    //獲得contentLength的值,後續不再調用
                    contentLength = body.contentLength();
                }
                //增加當前寫入的字節數
                bytesWritten += byteCount;
                //回調
                progressListener.update(bytesWritten, contentLength, bytesWritten == contentLength);
            }
        };
    }

}
基本步驟都完成了,接下來看看封裝的類MyRetrofit
public class MyRetrofit {

    private static String POST = "post";
    private static String GET = "get";

    /**
     * 此方法是調用Get和Post的請求的基礎
     * @param type
     * @param IP
     * @param url
     * @param para
     * @param handler
     * @param success
     * @param fail
     * @param marker
     * @param netSuccess
     */
    private static void BaseGetAndPost(String type,String IP,String url,Map<String,String> para, final Handler handler,
                               final int success, final int fail, final int marker, final NetSuccess netSuccess){
        Retrofit retrofit = new Retrofit.Builder()
                .addConverterFactory(StringConverterFactory.create())
                .baseUrl(IP)
                .build();
        MyRetrofitService service = retrofit.create(MyRetrofitService.class);
        Call<String> call = null;
        //判斷是POST請求還是GET請求
        if(type.equals(POST)){
            call = service.postService(url,para);
        }else if(type.equals(GET)){
            if(para != null && para.size() != 0) {
                call = service.getService(url, para);
            }else{
                call = service.getService(url);
            }
        }else {
            StringUtil.showMessage("參數出錯");
            return;
        }
        call.enqueue(new Callback<String>() {
            @Override
            public void onResponse(Call<String> call, Response<String> response) {
                int code = response.code();
                Message message = new Message();
                message.what = success;
                message.arg1 = marker;
                if(code == 200){
                    if(netSuccess != null){
                        message.obj = netSuccess.onSuccess(response.body().toString());
                    }
                }else {
                    StringUtil.showMessage("連接服務器出錯");
                }
                handler.sendMessage(message);
            }
            @Override
            public void onFailure(Call<String> call, Throwable throwable) {
                Message message = new Message();
                message.what = fail;
                message.obj = "FAIL";
                handler.sendMessage(message);
            }
        });
    }

    /**
     * 此方法爲單一文件和多文件的上傳的基礎方法
     * 傳遞過來的爲文件路徑,且能顯示上傳進度
     * @param IP
     * @param url
     * @param FilePath
     * @param description
     * @param handler
     * @param success
     * @param fail
     * @param marker
     * @param netSuccess
     */
    private static void putFileBase(String IP,String url,List<String> FilePath,String description,final Handler handler
            , final int success, final int fail, final int marker, final NetSuccess netSuccess,final ProgressListener listener){
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(IP)
                .addConverterFactory(StringConverterFactory.create())
                .build();
        MyRetrofitService service = retrofit.create(MyRetrofitService.class);
        Call<String> call = null;
        if(FilePath == null || FilePath.size() == 0){
            StringUtil.showMessage("請選擇文件");
            return;
        }else{
            if(FilePath.size() ==1) {//單文件上傳
                File file = new File(FilePath.get(0));
                RequestBody fileBody = RequestBody.create(MediaType.parse("multipart/form-data"), file);
                ProgressRequestBody requestBody = new ProgressRequestBody(fileBody,listener);
                MultipartBody.Part part = MultipartBody.Part.createFormData("file", file.getName(), requestBody);
                if (description == null) {
                    call = service.putService(url, part);
                } else {
                    RequestBody descriptionBody = RequestBody.create(null, description);
                    call = service.putService(url, part, descriptionBody);
                }
            }else{//多文件上傳
                Map<String,MultipartBody.Part> fileBody = null;
                for(int i=0;i<FilePath.size();i++){
                    File file = new File(FilePath.get(i));
                    RequestBody body = RequestBody.create(MediaType.parse("multipart/form-data"), file);
                    ProgressRequestBody requestBody = new ProgressRequestBody(body,listener);
                    MultipartBody.Part part = MultipartBody.Part.createFormData("file", file.getName(), requestBody);
                    fileBody.put(""+i,part);
                }
                if (description == null) {
                    call = service.putService(url, fileBody);
                } else {
                    RequestBody descriptionBody = RequestBody.create(null, description);
                    call = service.putService(url, fileBody, descriptionBody);
                }
            }
        }
        call.enqueue(new Callback<String>() {
            @Override
            public void onResponse(Call<String> call, Response<String> response) {
                int code = response.code();
                Message message = new Message();
                message.what = success;
                message.arg1 = marker;
                if(code == 200){
                    if(netSuccess != null){
                        message.obj = netSuccess.onSuccess(response.body().toString());
                    }
                }else{
                    StringUtil.showMessage("連接服務器出錯");
                }
                handler.sendMessage(message);
            }
            @Override
            public void onFailure(Call<String> call, Throwable throwable) {
                Message message = new Message();
                message.what = fail;
                message.obj = "FAIL";
                handler.sendMessage(message);
            }
        });
    }

    /**
     * 此方法爲單一文件和多文件的上傳的基礎方法
     * 一般用於圖片的上傳(可進行圖片的壓縮)
     * @param IP
     * @param url
     * @param FilePath
     * @param description
     * @param handler
     * @param success
     * @param fail
     * @param marker
     * @param netSuccess
     */
    private static void putFileBase(String IP,String url,List<String> FilePath,int width,int hight,String description
            ,final Handler handler, final int success, final int fail, final int marker, final NetSuccess netSuccess){
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(IP)
                .addConverterFactory(StringConverterFactory.create())
                .build();
        MyRetrofitService service = retrofit.create(MyRetrofitService.class);
        Call<String> call = null;
        if(FilePath == null || FilePath.size() == 0){
            StringUtil.showMessage("請選擇文件");
            return;
        }else{
            if(FilePath.size() ==1) {//單文件上傳
                File file = new File(FilePath.get(0));
                Bitmap bitmap = CommonUtil.changeBitmap(FilePath.get(0), width, hight);
                String[] arr = FilePath.get(0).split("\\.");
                int len = arr.length;
                byte[] byteArr = CommonUtil.bitMap2byteArr(bitmap, arr[len - 1]);
                RequestBody fileBody = RequestBody.create(MediaType.parse("multipart/form-data"), byteArr);
                MultipartBody.Part part = MultipartBody.Part.createFormData("file", file.getName(), fileBody);
                if (description == null) {
                    call = service.putService(url, part);
                } else {
                    RequestBody descriptionBody = RequestBody.create(null, description);
                    call = service.putService(url, part, descriptionBody);
                }
            }else{//多文件上傳
                Map<String,MultipartBody.Part> fileBody = null;
                for(int i=0;i<FilePath.size();i++){
                    File file = new File(FilePath.get(i));
                    Bitmap bitmap = CommonUtil.changeBitmap(FilePath.get(0), width, hight);
                    String[] arr = FilePath.get(i).split("\\.");
                    int len = arr.length;
                    byte[] byteArr = CommonUtil.bitMap2byteArr(bitmap, arr[len - 1]);
                    RequestBody body = RequestBody.create(MediaType.parse("multipart/form-data"),byteArr);
                    MultipartBody.Part part = MultipartBody.Part.createFormData("file", file.getName(), body);
                    fileBody.put(""+i,part);
                }
                if (description == null) {
                    call = service.putService(url, fileBody);
                } else {
                    RequestBody descriptionBody = RequestBody.create(null, description);
                    call = service.putService(url, fileBody, descriptionBody);
                }
            }
        }
        call.enqueue(new Callback<String>() {
            @Override
            public void onResponse(Call<String> call, Response<String> response) {
                int code = response.code();
                Message message = new Message();
                message.what = success;
                message.arg1 = marker;
                if(code == 200){
                    if(netSuccess != null){
                        message.obj = netSuccess.onSuccess(response.body().toString());
                    }
                }else{
                    StringUtil.showMessage("連接服務器出錯");
                }
                handler.sendMessage(message);
            }
            @Override
            public void onFailure(Call<String> call, Throwable throwable) {
                Message message = new Message();
                message.what = fail;
                message.obj = "FAIL";
                handler.sendMessage(message);
            }
        });
    }

    /**
     * 用於下載文件(應該先檢查文件是否存在)
     * @param IP
     * @param url
     * @param savePath
     * @param para
     * @param handler
     * @param success
     * @param fail
     * @param marker
     * @param netSuccess
     * @param listener
     */

    private static void getFileBase(String IP,String url, final String savePath,Map<String,String> para, final Handler handler
            , final int success, final int fail, final int marker, final NetSuccess netSuccess, final ProgressListener listener){
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(IP)
                .addConverterFactory(StringConverterFactory.create())
                .build();
        MyRetrofitService service = retrofit.create(MyRetrofitService.class);
        Call<ResponseBody> call = null;
        if(para ==null || para.size() ==0) {
            call = service.getFileService(url);
        }else{
            call = service.getFileService(url,para);
        }
        call.enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                int code = response.code();
                Message message = new Message();
                message.what = success;
                message.arg1 = marker;
                if(code == 200){
                    if(netSuccess != null){
                        ResponseBody body = response.body();
                        ProgressResponseBody responseBody = new ProgressResponseBody(body,listener);
                        byte[] bytes = new byte[0];
                        try {
                            bytes = responseBody.bytes();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        if(CommonUtil.saveBytesToFile(bytes,savePath)){
                            StringUtil.showMessage("下載完成");
                        }else{
                            StringUtil.showMessage("下載失敗");
                        }
                    }
                }else{
                    StringUtil.showMessage("連接服務器出錯");
                }
                handler.sendMessage(message);
            }
            @Override
            public void onFailure(Call<ResponseBody> call, Throwable throwable) {
                Message message = new Message();
                message.what = fail;
                message.obj = "FAIL";
                handler.sendMessage(message);
            }
        });
    }


    private static void getImageBase(String IP,String url,Map<String,String> para, final Handler handler
            , final int success, final int fail, final int marker){
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(IP)
                .addConverterFactory(StringConverterFactory.create())
                .build();
        MyRetrofitService service = retrofit.create(MyRetrofitService.class);
        Call<ResponseBody> call = null;
        if(para ==null || para.size() ==0) {
            call = service.getFileService(url);
        }else{
            call = service.getFileService(url,para);
        }
        call.enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                int code = response.code();
                Message message = new Message();
                message.what = success;
                message.arg1 = marker;
                if(code == 200){
                    ResponseBody body = response.body();
                    byte[] bytes = new byte[0];
                    try {
                        bytes = body.bytes();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    message.obj = CommonUtil.Bytes2Bimap(bytes);
                }else{
                    StringUtil.showMessage("連接服務器出錯");
                }
                handler.sendMessage(message);
            }
            @Override
            public void onFailure(Call<ResponseBody> call, Throwable throwable) {
                Message message = new Message();
                message.what = fail;
                message.obj = "FAIL";
                handler.sendMessage(message);
            }
        });
    }


    public interface NetSuccess{
        /**
         * 成功獲取數據
         * @param result json數據
         * @return 解析之後的結果
         */
        public <T> T onSuccess(T result);
    }


    /**
     * Get請求的使用方法
     * @param handler
     * @param name
     * @param marker
     */

    public static void getConCeShi(Handler handler,String name,int marker){
        Map<String,String> para = new HashMap<>();
        if(!StringUtil.isEmpty(name)) {
            para.put("name", name);
        }
        BaseGetAndPost(GET, Contents.IP, Contents.getCeShi, para, handler, Contents.SUCCESS,
                Contents.FAIL, marker, new NetSuccess() {
                    @Override
                    public <T> T onSuccess(T result) {
                        //返回的結果,字符串類型
                        return result;
                    }
                });
    }

    /**
     * Post請求的是用方法
     * @param handler
     * @param name
     * @param marker
     */
    public static void postConCeShi(Handler handler,String name,int marker){
        Map<String,String> para = new HashMap<>();
        if(!StringUtil.isEmpty(name)) {
            para.put("name", name);
        }
        BaseGetAndPost(POST, Contents.IP, Contents.postCeShi, para, handler, Contents.SUCCESS,
                Contents.FAIL, marker, new NetSuccess() {
                    @Override
                    public <T> T onSuccess(T result) {
                        //返回的結果,字符串類型
                        return result;
                    }
                });
    }


    /**
     * 文件的上傳圖片不需要壓縮的話也可以用此方法
     * @param handler
     * @param filePath
     * @param descrtion
     * @param marker
     */
    public static void putFileCeShi(Handler handler,List<String> filePath,String descrtion,int marker){

        putFileBase(Contents.IP, Contents.putCeShi, filePath, descrtion, handler, Contents.SUCCESS,
                Contents.FAIL, marker, new NetSuccess() {
                    @Override
                    public <T> T onSuccess(T result) {
                        //返回的結果,字符串類型
                        return result;
                    }
                }, new ProgressListener() {
                    @Override
                    public void update(long bytesRead, long contentLength, boolean done) {
                        //上傳進度的展示
                    }
                });
    }

    /**
     * 圖片的按照尺寸的壓縮上傳
     * @param handler
     * @param filePath
     * @param width
     * @param hight
     * @param descrtion
     * @param marker
     */
    public static void putImageCeShi(Handler handler,List<String> filePath,int width,int hight,String descrtion,int marker){

        putFileBase(Contents.IP, Contents.putCeShi, filePath,width,hight, descrtion, handler, Contents.SUCCESS,
                Contents.FAIL, marker, new NetSuccess() {
                    @Override
                    public <T> T onSuccess(T result) {
                        return result;
                    }
                });
    }


    public static void getFileCeShi(Handler handler,String savePath,String curfile,String path,int marker){
        Map<String,String> para = new HashMap<>();
        para.put("curfile",curfile);
        para.put("path",path);
        getFileBase(Contents.IP, Contents.setCeShi, savePath, para, handler, Contents.SUCCESS,
                Contents.FAIL, marker, new NetSuccess() {
                    @Override
                    public <T> T onSuccess(T result) {
                        return null;
                    }
                }, new ProgressListener() {
                    @Override
                    public void update(long bytesRead, long contentLength, boolean done) {
                        //此處顯示下載進度的對應UI
                    }
                });
    }

    public static void displayNetImage(Handler handler,String curfile,String path,int marker){
        Map<String,String> para = new HashMap<>();
        para.put("curfile",curfile);
        para.put("path",path);
        getImageBase(Contents.IP, Contents.setCeShi, para, handler, Contents.SUCCESS, Contents.FAIL
                , marker);
    }


}
到此已經是封裝完成了,使用方法如下:
//GET請求的測試
//                MyRetrofit.getConCeShi(handler,"", BackMakerUtil.CESHIBACK);
                //Post請求的測試
//                MyRetrofit.postConCeShi(handler,"fei",BackMakerUtil.CESHIBACK);
                //文件上傳(有說明信息就寫,沒有就傳null,不需要壓縮的圖片也可以用此方法)
//                MyRetrofit.putFileCeShi(handler, file, "fei", BackMakerUtil.CESHIBACK);
                //需要壓縮的圖片的上傳
//                MyRetrofit.putImageCeShi(handler, file, 300, 150, "fei", BackMakerUtil.CESHIBACK);
                //下載文件
//                MyRetrofit.getFileCeShi(handler,path,"a.jpg","D:/aDown",BackMakerUtil.CESHIBACK);
                //加載圖片
                MyRetrofit.displayNetImage(handler,"a.jpg","D://aDown",BackMakerUtil.CESHIBACK);

到此就全部寫完了,希望看到各位能提出寶貴的看法
本人只是一個Android菜鳥,由於還不會RxJava,所以只能這樣封裝了,學會了RxJava還會繼續採用RxJava+Retrofit的方法進行封裝
























發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章