美文网首页
Retrofit基本使用

Retrofit基本使用

作者: 小和尚恋红尘 | 来源:发表于2018-08-26 16:51 被阅读0次

上一章节讲解了OkHttp的基本使用,这节就来看看Retrofit的基本使用
调用的网址如下:

    public static final String RETROFIT_BASE_URL = "https://api.douban.com/";
    public static final String POS_HTTP_WEATHER = "http://api.k780.com:88/";
    public static final String URL_IMAGE_01 = "http://d.hiphotos.baidu.com/";
Retrofit的单独使用
  • GETQuery的使用
    @GET("/v2/book/search?")
    Call<BookInfo> getDuBanDataUseQuery(@Query("q") String bookName, @Query("tag") String tag, @Query("start") int start, @Query("count") int count);

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(UrlUtils.RETROFIT_BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        RetrofitApi retrofitApi = retrofit.create(RetrofitApi.class);
        Call<BookInfo> duBanDataCall = retrofitApi.getDuBanDataUseQuery("小王子", null, 0, 3);
        duBanDataCall.enqueue(new Callback<BookInfo>() {
            @Override
            public void onResponse(Call<BookInfo> call, Response<BookInfo> response) {
                if (response != null && response.body() != null) {
                    List<Book> results = response.body().getBooks();
                    for (Book book : results) {
                        Log.e("LHC", "bookTitle:" + book.getTitle() + ", bookAuthor:" + book.getAuthor()[0]);
                    }
                }
            }

            @Override
            public void onFailure(Call<BookInfo> call, Throwable t) {
                ToastUtils.showShort("调用失败");
                t.printStackTrace();
            }
        });
  • GETQueryMap的使用
    @GET("v2/book/search?")
    Call<BookInfo> getDuBanDataUseQueryMap(@QueryMap Map<String, String> options);

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(UrlUtils.RETROFIT_BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        RetrofitApi retrofitApi = retrofit.create(RetrofitApi.class);

        Map<String, String> options = new HashMap<>();
        options.put("q", "小王子");
        options.put("tag", "");
        options.put("start", "0");
        options.put("count", "3");
        Call<BookInfo>  duBanDataCall = retrofitApi.getDuBanDataUseQueryMap(options);
        duBanDataCall.enqueue(new Callback<BookInfo>() {
            @Override
            public void onResponse(Call<BookInfo> call, Response<BookInfo> response) {
                if (response != null && response.body() != null) {
                    List<Book> results = response.body().getBooks();
                    for (Book book : results) {
                        Log.e("LHC", "bookTitle:" + book.getTitle() + ", bookAuthor:" + book.getAuthor()[0]);
                    }
                }
            }

            @Override
            public void onFailure(Call<BookInfo> call, Throwable t) {
                ToastUtils.showShort("调用失败");
                t.printStackTrace();
            }
        });
  • GETPath的使用
    @GET("v2/book/{id}")
    Call<Book> getDuBanDataUsePath(@Path("id") String id);

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(UrlUtils.RETROFIT_BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        RetrofitApi retrofitApi = retrofit.create(RetrofitApi.class);
        Call<Book> duBanDataUsePathCall = retrofitApi.getDuBanDataUsePath("1003078");
        duBanDataUsePathCall.enqueue(new Callback<Book>() {
            @Override
            public void onResponse(Call<Book> call, Response<Book> response) {
                if (response != null && response.body() != null) {
                    Book book = response.body();
                    Log.e("LHC", "bookTitle:" + book.getTitle() + ", bookAuthor:" + book.getAuthor()[0]);
                }
            }

            @Override
            public void onFailure(Call<Book> call, Throwable t) {
                ToastUtils.showShort("调用失败");
                t.printStackTrace();
            }
        });
  • POSTField的使用
    @FormUrlEncoded
    @POST("/?")
    Call<Weathers> getWeathersData(@Field("app") String app, @Field("weaid") String weaId, @Field("appkey") String appKey, @Field("sign") String sign, @Field("format") String format);

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(UrlUtils.POS_HTTP_WEATHER)
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        RetrofitApi retrofitApi = retrofit.create(RetrofitApi.class);
        Call<Weathers> weathersDataCall = retrofitApi.getWeathersData("weather.future", "1", "10003", "b59bc3ef6191eb9f747dd4e83c99f2a4", "json");
        weathersDataCall.enqueue(new Callback<Weathers>() {
            @Override
            public void onResponse(Call<Weathers> call, Response<Weathers> response) {
                if (response != null && response.body() != null) {
                    List<WeatherInfo> results = response.body().getResult();
                    for (WeatherInfo weatherInfo : results) {
                        Log.e("LHC", "cityName:" + weatherInfo.getCitynm() + ", days:" + weatherInfo.getDays() + ", temperature:" + weatherInfo.getTemperature());
                    }
                }
            }

            @Override
            public void onFailure(Call<Weathers> call, Throwable t) {
                ToastUtils.showShort("调用失败");
            }
        });
  • POSTFieldMap的使用
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(UrlUtils.POS_HTTP_WEATHER)
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        RetrofitApi retrofitApi = retrofit.create(RetrofitApi.class);
            Map<String, String> options = new HashMap<>();
            options.put("app", "weather.future");
            options.put("weaid", "1");
            options.put("appkey", "10003");
            options.put("sign", "b59bc3ef6191eb9f747dd4e83c99f2a4");
            options.put("format", "json");
            Call<Weathers> weathersDataCall = retrofitApi.getWeathersData(options);
        weathersDataCall.enqueue(new Callback<Weathers>() {
            @Override
            public void onResponse(Call<Weathers> call, Response<Weathers> response) {
                if (response != null && response.body() != null) {
                    List<WeatherInfo> results = response.body().getResult();
                    for (WeatherInfo weatherInfo : results) {
                        Log.e("LHC", "cityName:" + weatherInfo.getCitynm() + ", days:" + weatherInfo.getDays() + ", temperature:" + weatherInfo.getTemperature());
                    }
                }
            }

            @Override
            public void onFailure(Call<Weathers> call, Throwable t) {
                ToastUtils.showShort("调用失败");
            }
        });
  • POSTBody的使用
//没有调用成功
  • 下载文件
    @Streaming
    @GET("zhidao/pic/item/0bd162d9f2d3572c5a387f618c13632763d0c3b1.jpg")
    Call<ResponseBody> downFile();

    private String FILE_DIR = Environment.getExternalStorageDirectory() + File.separator + "downImage";
    private String FILE_NAME = "ok_" + System.currentTimeMillis() + ".jpg";

    private void downLoadImage() {
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(UrlUtils.URL_IMAGE_01)
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        RetrofitApi retrofitApi = retrofit.create(RetrofitApi.class);
        Call<ResponseBody> call = retrofitApi.downFile();
        call.enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call, final Response<ResponseBody> response) {
                if (response != null && response.body() != null) {
                    ThreadUtil.getInstance().getExecutorService().execute(new Runnable() {
                        @Override
                        public void run() {
                            writeFileToDisk(response);
                        }
                    });
                }
            }

            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {
                t.printStackTrace();
            }
        });
    }

    private void writeFileToDisk(Response<ResponseBody> response) {
        InputStream is = null;
        FileOutputStream fos = null;
        try {
            byte[] buff = new byte[2048];
            is = response.body().byteStream();
            File filePath = new File(FILE_DIR);
            if (!filePath.mkdirs()) {
                filePath.createNewFile();
            }
            final File file = new File(filePath, FILE_NAME);
            fos = new FileOutputStream(file);
            int len = 0;
            while ((len = is.read(buff)) != -1) {
                fos.write(buff, 0, len);
            }
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    Glide.with(RetrofitMainActivity.this).load(file.getAbsoluteFile()).into(ivShow);
                }
            });
            fos.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
  • 上传文件
    @Multipart
    @POST("xxx/uploadImage")
    Call<FileBean> upLoadMultiFile1(@Part MultipartBody.Part[] parts);

    private void upLoadMultiFile1() {
        List<File> files = getFiles();
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(UrlUtils.URL_UPLOAD_BASE)
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        RetrofitApi retrofitApi = retrofit.create(RetrofitApi.class);
        MultipartBody.Part[] parts = new MultipartBody.Part[files.size()];
        for (int i = 0; i < files.size(); i++) {
            File file = files.get(i);
            RequestBody requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), file);
            MultipartBody.Part filePart = MultipartBody.Part.createFormData(file.getName(), requestFile);
            parts[i] = filePart;
        }

        Call<FileBean> fileBeanCall = retrofitApi.upLoadMultiFile1("files", parts);
        fileBeanCall.enqueue(new Callback<FileBean>() {
            @Override
            public void onResponse(Call<FileBean> call, Response<FileBean> response) {
                List<String> result = response.body().getResult();
                for (String s : result) {
                    Log.e("LHC", "imgUrl:\n"+ s);
                }
            }

            @Override
            public void onFailure(Call<FileBean> call, Throwable t) {
                t.printStackTrace();
            }
        });
    }

    private List<File> getFiles() {
        List<File> files = new ArrayList<>();
        files.add(new File(Environment.getExternalStorageDirectory()+File.separator+"crop_image.jpg"));
        files.add(new File(Environment.getExternalStorageDirectory()+File.separator+"temp.png"));
        return files;
    }
Retrofit+RxJava联合使用
  • GETQueryMap的使用
    @GET("v2/book/search?")
    Observable<BookInfo> getDuBanDataUseQueryMap1(@QueryMap Map<String, String> options);

    private void getQueryMap() {
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(UrlUtils.RETROFIT_BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();
        RetrofitApi retrofitApi = retrofit.create(RetrofitApi.class);

        Map<String, String> options = new HashMap<>();
        options.put("q", "小王子");
        options.put("tag", "");
        options.put("start", "0");
        options.put("count", "3");
        Observable<BookInfo> duBanDataUseQueryMap = retrofitApi.getDuBanDataUseQueryMap1(options);
        duBanDataUseQueryMap.observeOn(AndroidSchedulers.mainThread())
                .subscribeOn(Schedulers.io()).subscribe(new Observer<BookInfo>() {
            @Override
            public void onCompleted() {
                ToastUtils.showShort("调用成功");
            }

            @Override
            public void onError(Throwable e) {
                ToastUtils.showShort("调用失败");
                e.printStackTrace();
            }

            @Override
            public void onNext(BookInfo bookInfo) {
                List<Book> results = bookInfo.getBooks();
                for (Book book : results) {
                    Log.e("LHC", "bookTitle:" + book.getTitle() + ", bookAuthor:" + book.getAuthor()[0]);
                }
            }
        });
    }
  • POSTFieldMap的使用
    @FormUrlEncoded
    @POST("/?")
    Observable<Weathers> getWeathersData1(@FieldMap Map<String, String> options);

    private void postFieldMap() {
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(UrlUtils.POS_HTTP_WEATHER)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();
        RetrofitApi retrofitApi = retrofit.create(RetrofitApi.class);

        Map<String, String> options = new HashMap<>();
        options.put("app", "weather.future");
        options.put("weaid", "1");
        options.put("appkey", "10003");
        options.put("sign", "b59bc3ef6191eb9f747dd4e83c99f2a4");
        options.put("format", "json");
        Observable<Weathers> duBanDataUseQueryMap = retrofitApi.getWeathersData1(options);
        duBanDataUseQueryMap.observeOn(AndroidSchedulers.mainThread())
                .subscribeOn(Schedulers.io()).subscribe(new Observer<Weathers>() {
            @Override
            public void onCompleted() {
                ToastUtils.showShort("调用成功");
            }

            @Override
            public void onError(Throwable e) {
                ToastUtils.showShort("调用失败");
                e.printStackTrace();
            }

            @Override
            public void onNext(Weathers bookInfo) {
                List<WeatherInfo> results = bookInfo.getResult();
                for (WeatherInfo weatherInfo : results) {
                    Log.e("LHC", "cityName:" + weatherInfo.getCitynm() + ", days:" + weatherInfo.getDays() + ", temperature:" + weatherInfo.getTemperature());
                }
            }
        });
    }
  • 下载文件
//    @Streaming //单独使用`Retrofit`时,加上此参数并没有报错,但是和`RxJava`联合起来使用时,会出现错误
    @GET("zhidao/pic/item/0bd162d9f2d3572c5a387f618c13632763d0c3b1.jpg")
    Observable<ResponseBody> downFile1();

    private String FILE_DIR = Environment.getExternalStorageDirectory() + File.separator + "downImage";
    private String FILE_NAME = "ok_" + System.currentTimeMillis() + ".jpg";
    private void downImage() {
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(UrlUtils.URL_IMAGE_01)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();
        RetrofitApi retrofitApi = retrofit.create(RetrofitApi.class);
        Observable<ResponseBody> observable = retrofitApi.downFile1();
        observable.observeOn(AndroidSchedulers.mainThread())
                .subscribeOn(Schedulers.io())
                .subscribe(new Observer<ResponseBody>() {
                    @Override
                    public void onCompleted() {
                        Log.e("LHC", "下载成功");
                    }

                    @Override
                    public void onError(Throwable e) {
                        Log.e("LHC", "下载失败");
                        e.printStackTrace();
                    }

                    @Override
                    public void onNext(final ResponseBody responseBody) {
                        mHandler = ThreadUtil.getInstance().getHandler();
                        ThreadUtil.getInstance().getExecutorService().execute(new Runnable() {
                            @Override
                            public void run() {
                                writeFileToDisk(responseBody);//
                            }
                        });
                    }
                });
    }

从上面可以看到,RetrofitRetrofit+RxJava的使用差不多,不用在与接口返回值和回调方法。所以这里就只列举这几个。

Retrofit+RxJava的简单封装
public class RetrofitUtils {
    private static RetrofitUtils mRetrofitUtils;
    private Retrofit mRetrofit;
    private String FILE_DIR = Environment.getExternalStorageDirectory() + File.separator + "downImage";
    private String FILE_NAME = "ok_" + System.currentTimeMillis() + ".jpg";

    public static RetrofitUtils getInstance(){
        if (mRetrofitUtils == null){
            synchronized (RetrofitUtils.class){
                if (mRetrofitUtils == null){
                    mRetrofitUtils = new RetrofitUtils();
                }
            }
        }
        return mRetrofitUtils;
    }

    public <T>T getRetrofitApi(Class<T> cls, String baseUrl){
        return getRetrofit(baseUrl).create(cls);
    }

    private Retrofit getRetrofit(String baseUrl){
        if (mRetrofit == null){
            mRetrofit = new Retrofit.Builder()
                    .baseUrl(baseUrl)
                    .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
        }
        return mRetrofit;
    }

    public <T> void init(Observable<T>  observable, Subscriber<T>  subScribe){
        observable
                .observeOn(AndroidSchedulers.mainThread())
                .subscribeOn(Schedulers.io())
                .subscribe(subScribe);
    }

    public <T> void init(Observable<T> observable, ApiCallback<T> callback){
        observable
                .observeOn(AndroidSchedulers.mainThread())
                .subscribeOn(Schedulers.io())
                .subscribe(getSubscriber(callback));
    }

    private <T> Subscriber<T> getSubscriber(final ApiCallback<T> callback){
        return new Subscriber<T>() {
            @Override
            public void onCompleted() {
            }

            @Override
            public void onError(Throwable e) {
                callback.onError("调用失败");
                e.printStackTrace();
            }

            @Override
            public void onNext(T t) {
                callback.onSuccess(t);
            }
        };
    }
    
    public void writeFileToDisk(ResponseBody response, DownloadCallback callback) {
        InputStream is = null;
        FileOutputStream fos = null;
        try {
            byte[] buff = new byte[2048];
            is = response.byteStream();
            File filePath = new File(FILE_DIR);
            if (!filePath.exists()) {
                filePath.mkdirs();
            }
            final File file = new File(filePath, FILE_NAME);
            fos = new FileOutputStream(file);

            int len = 0;
            while ((len = is.read(buff)) != -1) {
                fos.write(buff, 0, len);
            }
            callback.getImageFile(file.getAbsolutePath());
            fos.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public interface ApiCallback<T>{
        void onSuccess(T t);
        void onError(String msg);
    }

    public interface DownloadCallback{
        void getImageFile(String imgFile);
    }
}
  • GETQueryMap的使用
                Map<String, String> options = new HashMap<>();
                options.put("q", "小王子");
                options.put("tag", "");
                options.put("start", "0");
                options.put("count", "3");
                mRetrofitUtils.init(mRetrofitUtils.getRetrofitApi(RetrofitApi.class, UrlUtils.RETROFIT_BASE_URL).getDuBanDataUseQueryMap1(options), new Subscriber<BookInfo>() {
                    @Override
                    public void onCompleted() {
                        ToastUtils.showShort("调用成功");
                    }

                    @Override
                    public void onError(Throwable e) {
                        ToastUtils.showShort("调用失败");
                        e.printStackTrace();
                    }

                    @Override
                    public void onNext(BookInfo bookInfo) {
                        List<Book> results = bookInfo.getBooks();
                        for (Book book : results) {
                            Log.e("LHC", "bookTitle:" + book.getTitle() + ", bookAuthor:" + book.getAuthor()[0]);
                        }
                    }
                });
  • POSTFieldMap的使用
                Map<String, String> map = new HashMap<>();
                map.put("app", "weather.future");
                map.put("weaid", "1");
                map.put("appkey", "10003");
                map.put("sign", "b59bc3ef6191eb9f747dd4e83c99f2a4");
                map.put("format", "json");
                mRetrofitUtils.init(mRetrofitUtils.getRetrofitApi(RetrofitApi.class, UrlUtils.POS_HTTP_WEATHER).getWeathersData1(map), new RetrofitUtils.ApiCallback<Weathers>() {
                    @Override
                    public void onSuccess(Weathers weathers) {
                        List<WeatherInfo> results = weathers.getResult();
                        for (WeatherInfo weatherInfo : results) {
                            Log.e("LHC", "cityName:" + weatherInfo.getCitynm() + ", days:" + weatherInfo.getDays() + ", temperature:" + weatherInfo.getTemperature());
                        }
                    }

                    @Override
                    public void onError(String msg) {
                        ToastUtils.showShort(msg);
                    }
                });
  • 下载文件
                mRetrofitUtils.init(mRetrofitUtils.getRetrofitApi(RetrofitApi.class, UrlUtils.URL_IMAGE_01).downFile1(), new RetrofitUtils.ApiCallback<ResponseBody>() {
                    @Override
                    public void onSuccess(final ResponseBody responseBody) {
                        ThreadUtil.getInstance().getExecutorService().execute(new Runnable() {
                            @Override
                            public void run() {
                                mRetrofitUtils.writeFileToDisk(responseBody, new RetrofitUtils.DownloadCallback() {
                                    @Override
                                    public void getImageFile(final String imgFile) {

                                        runOnUiThread(new Runnable() {
                                            @Override
                                            public void run() {
                                                Glide.with(RetrofitRxJavaFZActivity.this).load(imgFile).into(ivShow);
                                            }
                                        });
                                    }
                                });
                            }
                        });
                    }

                    @Override
                    public void onError(String msg) {
                        ToastUtils.showShort(msg);
                    }
                });
  • 上传文件
    @Multipart
    @POST("xxx/uploadImage")
    Observable<FileBean> upLoadMultiFile2(@Part MultipartBody.Part[] parts);

                File file = new File(Environment.getExternalStorageDirectory()+File.separator+"crop_image.jpg");
                File file1 = new File(Environment.getExternalStorageDirectory()+File.separator+"temp.png");
                List<File> files = new ArrayList<>();
                files.add(file);
                files.add(file1);
                MultipartBody.Part[] parts = new MultipartBody.Part[files.size()];
                for (int i = 0; i < files.size(); i++) {
                    File fileItem = files.get(i);
                    RequestBody requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), fileItem);
                    MultipartBody.Part filePart = MultipartBody.Part.createFormData("files", fileItem.getName(), requestFile);
                    parts[i] = filePart;
                }
                mRetrofitUtils.init(mRetrofitUtils.getRetrofitApi(RetrofitApi.class, UrlUtils.URL_UPLOAD_BASE).upLoadMultiFile2(parts), new RetrofitUtils.ApiCallback<FileBean>() {
                    @Override
                    public void onSuccess(FileBean bean) {
                        Log.e("LHC", "imgUrl:\n"+ bean.getResult().get(0)+"\n"+bean.getResult().get(1));
                    }

                    @Override
                    public void onError(String msg) {
                        ToastUtils.showShort("上传失败");
                    }
                });

这样Retrofit基本使用就完成了。
OKGO是对Retrofit的再次封装,使用很方便,地址:https://github.com/jeasonlzy/okhttp-OkGo

相关文章

  • Retrofit2源码分析

    Retrofit源码分析基于2.4.0。 关于Retrofit的基本使用可以参照 Retrofit官网。 Retr...

  • Retrofit 2.0的封装与异常处理

    Retrofit 2.0的基本使用,网上教程很多,Retrofit 官方教程 定义接口 初始化Retrofit 调...

  • Retrofit基本使用

    Retrofit 作为Android和Java类型安全的HTTP客户端,记得刚毕业那会面试,面试官问我用过Retr...

  • Retrofit基本使用

    上一章节讲解了OkHttp的基本使用,这节就来看看Retrofit的基本使用调用的网址如下: Retrofit的单...

  • Retrofit基本使用

    Retrofit基本使用 内容 基础 接口配置 发送请求异步请求 && 示例一Convert && 示例二RxJa...

  • Retrofit基本使用

    Retrofit是由著名的 Square 公司开源的一个基于OkHttp实现网络请求的框架,以其简易的接口配置、强...

  • Retrofit基本使用

    导包 参数注解 @GET(): 注解在方法上,表示get请求,括号内为请求url @POST(): 注解在方法上,...

  • Retrofit2

    一、Retrofit2 GitHub:Retrofit2Demo 二、Retrofit2概念 三、使用 四、基本使...

  • Retrofit学习(二)

    之前的Retrofit学习(一)了解了一下Retrofit的最基本使用,不过目前最流行的Retrofit使用方式是...

  • Retrofit2网络框架的使用(二)扩展

    我们学习了Retrofit的基本使用后,我们知道Retrofit内部其实还是由Okhttp实现的,Retrofit...

网友评论

      本文标题:Retrofit基本使用

      本文链接:https://www.haomeiwen.com/subject/sfeoiftx.html