欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Android网络请求框架(三) Retrofit配合RxJava

程序员文章站 2022-06-15 22:18:34
大家好,好久没有更新了,今天给大家介绍一下目前火了很久很久的框架,Retrofit加RxJava配合使用介绍优点使用必要操作请求方法,请求头,请求参数表格介绍@GET请求:@POST请求打开本地相册选取图片上传图片@Url使用:xJava配合使用)介绍retrofit是okhttp的加强版,底层封装了Okhttp。准确来说,Retrofit是一个RESTful的http网络请求框架的封装。因为网络请求工作本质上是由okhttp来完成,而Retrofit负责网络请求接口的封装。优点超级解耦...

大家好,好久没有更新了,今天给大家介绍一下目前火了很久很久的框架,Retrofit加R xJava配合使用


xJava配合使用)

介绍

retrofit是okhttp的加强版,底层封装了Okhttp。准确来说,Retrofit是一个RESTful的http网络请求框架的封装。因为网络请求工作本质上是由okhttp来完成,而Retrofit负责网络请求接口的封装。

优点

  • 超级解耦

  • 支持同步、异步、Rxjava

  • 可以配置不同反序列化工具类来解析不同的数据,如json、xml

  • 请求速度快,使用方便灵活简洁

使用必要操作

添加依赖:


    //Retrofit:
    implementation 'com.squareup.retrofit2:retrofit:2.9.0'
    implementation 'com.squareup.retrofit2:converter-gson:2.4.0'


    //glide4:		//用于图片处理
    implementation 'com.github.bumptech.glide:glide:4.8.0'
    annotationProcessor 'com.github.bumptech.glide:compiler:4.8.0'

    //RxJava:
    implementation "io.reactivex.rxjava2:rxjava:2.1.3" // 必要rxjava2依赖
    implementation "io.reactivex.rxjava2:rxandroid:2.0.1" // 必要rxandrroid依赖,切线程时需要用到
    implementation 'com.squareup.retrofit2:adapter-rxjava2:2.4.0' // 必要依赖,和Retrofit结合必须用到,下面会提到

    /**
     *      日志拦截器
     */
    implementation 'com.squareup.okhttp3:logging-interceptor:3.3.1'

请求方法,请求头,请求参数表格介绍

请求方法:

注解 说明
@GET get请求
@POST post请求
@PUT put请求
@DELETE delete请求
@PATCH patch请求
@HEAD head请求 : 用于更新局部资源
@OPTIONS options请求
@HTTP put请求通过注解,可以替换以上所有的注解,它拥有三个属性:method、path、hasBody

本篇只给大家讲解常用的请求方法@GET,@POST和@HTTP请求.

请求头:

请求头注解 说明
@Headers 用于添加固定请求头,可以同时添加多个,通过该注解的请求头不会相互覆盖,而是共同存在
@Header 作为方法的参数传入,用于添加不固定的header,它会更新已有请求头

本篇不给大家讲解请求头,请求头可以通过代码来写入,因为太多注解容易搞混,这里也不建议大家使用注解的方法添加请求头.

请求参数:

请求参数 说明
@Body 多用于POST请求发送非表达数据,根据转换方式将实例对象转化为对应字符串传递参数,比如使用Post发送Json数据,添加GsonConverterFactory则是将body转化为json字符串进行传递
@Filed 用于POST请求 需要结合@FromUrlCoded以表单形式传递参数
@FiledMap 用于POST请求中的表单字段,传递多个参数,需要结合@FromUrlEncoded使用
@Part 用于POST请求,与@multipart配合使用,多用于上传单个文件
@PartMap 用于POST请求,与@multipart配合使用,多用于上传多个文件
@Path Url中的占位符
@Query 用于Get请求中的参数
@QueryMap 与Query类似,用于不确定表单参数
@Url 指定请求路径

请求和响应格式:

请求和响应格式(标记)注解 说明
@FromUrlEncoded @FiledMap 和 @Filed 使用的时候必须添加
@Multipart @PartMap 和 @Part 使用的时候必须添加
@Streaming 表示响应用字节流的形式返回,如果没有使用注解,默认会把数据全部载入到内存中,该注解在下载大文件时特别有用

@GET请求:

先定义一个接口:

public interface ApiServer {

	//定义要请求的接口前半段,注意:这里必须以/结尾!!!
    public static String BaseUri = "https://gank.io/api/data/%E7%A6%8F%E5%88%A9/";

	 /**
     *      通过调用getMeiNvBen()使用@Path注解,将传过来的参数设置给@GET()
     *      实现GET的传递 
     */
 	@GET("{number}/{index}")
    Observable<MeiNvBean> getMeiNvBean(@Path("number")String number, @Path("index")String index);

	/**
     *
     * @param method    网络请求的方法(区分大小写)
     * @param path      网络请求地址路径
     * @param hasBody  是否有请求体
     * @return
     */
    @HTTP(method = "GET",path = "{number}/{index}" ,hasBody = false)
    Observable<MeiNvBean> getHttpMeiNvBean(@Path("number")String number, @Path("index")String index);

}

我的MeiNvBean类是通过Postman软件来请求数据,然后通过GsonFromat来得到对应的实体类:

Android网络请求框架(三) Retrofit配合RxJava

获取MeiNvBean 实体类:

package demo.ht.com.volley.bean;

import java.util.List;

public class MeiNvBean {

    /**
     * error : false
     * results : [{"_id":"5be14edb9d21223dd50660f8","createdAt":"2018-11-06T08:20:43.656Z","desc":"2018-11-06","publishedAt":"2018-11-06T00:00:00.0Z","source":"web","type":"福利","url":"https://img.lijinshan.site/images/8733844e0b954e7e8e29102cefa32dbf","used":true,"who":"lijinshanmx"},{"_id":"5bcd71979d21220315c663fc","createdAt":"2018-10-22T06:43:35.440Z","desc":"2018-10-22","publishedAt":"2018-10-22T00:00:00.0Z","source":"web","type":"福利","url":"https://img.lijinshan.site/images/0bc3ed0deda74674b45bebb140bb5928","used":true,"who":"lijinshanmx"},{"_id":"5bc434ac9d212279160c4c9e","createdAt":"2018-10-15T06:33:16.497Z","desc":"2018-10-15","publishedAt":"2018-10-15T00:00:00.0Z","source":"web","type":"福利","url":"https://img.lijinshan.site/images/1635f0ffd94f40ff8058c2c4ff652e61","used":true,"who":"lijinshanmx"},{"_id":"5bbb0de09d21226111b86f1c","createdAt":"2018-10-08T07:57:20.978Z","desc":"2018-10-08","publishedAt":"2018-10-08T00:00:00.0Z","source":"web","type":"福利","url":"https://img.lijinshan.site/images/e930b75f48ae40b0a23f827e619d76a3","used":true,"who":"lijinshanmx"},{"_id":"5ba206ec9d2122610aba3440","createdAt":"2018-09-19T08:21:00.295Z","desc":"2018-09-19","publishedAt":"2018-09-19T00:00:00.0Z","source":"web","type":"福利","url":"https://img.lijinshan.site/images/d19c8feacc884e18898034c79e6e1a9d","used":true,"who":"lijinshanmx"},{"_id":"5b9771a29d212206c1b383d0","createdAt":"2018-09-11T07:41:22.491Z","desc":"2018-09-11","publishedAt":"2018-09-11T00:00:00.0Z","source":"web","type":"福利","url":"https://img.lijinshan.site/images/38ddf2ca672345889343b5748ffce78d","used":true,"who":"lijinshanmx"},{"_id":"5b830bba9d2122031f86ee51","createdAt":"2018-08-27T04:21:14.703Z","desc":"2018-08-27","publishedAt":"2018-08-28T00:00:00.0Z","source":"web","type":"福利","url":"https://img.lijinshan.site/images/a8aa7df22298413e9ca37c7a634e3425","used":true,"who":"lijinshanmx"},{"_id":"5b7b836c9d212201e982de6e","createdAt":"2018-08-21T11:13:48.989Z","desc":"2018-08-21","publishedAt":"2018-08-21T00:00:00.0Z","source":"web","type":"福利","url":"https://ws1.sinaimg.cn/large/0065oQSqly1fuh5fsvlqcj30sg10onjk.jpg","used":true,"who":"lijinshanmx"}]
     */

    private boolean error;
    private List<ResultsBean> results;

    @Override
    public String toString() {
        return "MeiNvBean{" +
                "error=" + error +
                ", results=" + results +
                '}';
    }

    public boolean isError() {
        return error;
    }

    public void setError(boolean error) {
        this.error = error;
    }

    public List<ResultsBean> getResults() {
        return results;
    }

    public void setResults(List<ResultsBean> results) {
        this.results = results;
    }

    public static class ResultsBean {
        /**
         * _id : 5be14edb9d21223dd50660f8
         * createdAt : 2018-11-06T08:20:43.656Z
         * desc : 2018-11-06
         * publishedAt : 2018-11-06T00:00:00.0Z
         * source : web
         * type : 福利
         * url : https://img.lijinshan.site/images/8733844e0b954e7e8e29102cefa32dbf
         * used : true
         * who : lijinshanmx
         */

        private String _id;
        private String createdAt;
        private String desc;
        private String publishedAt;
        private String source;
        private String type;
        private String url;
        private boolean used;
        private String who;

        @Override
        public String toString() {
            return "ResultsBean{" +
                    "_id='" + _id + '\'' +
                    ", createdAt='" + createdAt + '\'' +
                    ", desc='" + desc + '\'' +
                    ", publishedAt='" + publishedAt + '\'' +
                    ", source='" + source + '\'' +
                    ", type='" + type + '\'' +
                    ", url='" + url + '\'' +
                    ", used=" + used +
                    ", who='" + who + '\'' +
                    '}';
        }

        public String get_id() {
            return _id;
        }

        public void set_id(String _id) {
            this._id = _id;
        }

        public String getCreatedAt() {
            return createdAt;
        }

        public void setCreatedAt(String createdAt) {
            this.createdAt = createdAt;
        }

        public String getDesc() {
            return desc;
        }

        public void setDesc(String desc) {
            this.desc = desc;
        }

        public String getPublishedAt() {
            return publishedAt;
        }

        public void setPublishedAt(String publishedAt) {
            this.publishedAt = publishedAt;
        }

        public String getSource() {
            return source;
        }

        public void setSource(String source) {
            this.source = source;
        }

        public String getType() {
            return type;
        }

        public void setType(String type) {
            this.type = type;
        }

        public String getUrl() {
            return url;
        }

        public void setUrl(String url) {
            this.url = url;
        }

        public boolean isUsed() {
            return used;
        }

        public void setUsed(boolean used) {
            this.used = used;
        }

        public String getWho() {
            return who;
        }

        public void setWho(String who) {
            this.who = who;
        }
    }
}

使用最原始未封装GET请求数据:

Retrofit apiServer = new Retrofit.Builder().
                addCallAdapterFactory(RxJava2CallAdapterFactory.create()).
                addConverterFactory(GsonConverterFactory.create())
                .baseUrl(ApiServer.BaseUri)
                .build();

//        apiServer.create(ApiServer.class).getHttpMeiNvBean("8","1")
        apiServer.create(ApiServer.class).getMeiNvBean("8", "1")
                .subscribeOn(Schedulers.io())//IO线程
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<MeiNvBean>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(MeiNvBean meiNvBean) {
                        mTv.setText(meiNvBean.toString());
                        Log.i("szjonNex", meiNvBean.toString());
                    }

                    @Override
                    public void onError(Throwable e) {
                        mTv.setText("请求错误:" + e.getMessage());
                        Log.i("onError", e.getMessage());
                    }

                    @Override
                    public void onComplete() {

                    }
                });

来康康Log吧:
Android网络请求框架(三) Retrofit配合RxJava

@POST请求

还是先定义接口来实现请求接口的声明:


public interface ApiServer {
	//定义要请求的接口前半段,注意:这里必须以/结尾!!!
	public static String GuoChuangYun_BaseUri = "http://hn216.api.yesapi.cn/";

	 /**
     *
     * @param FormUrlEncoded   通过FieldMap上传必须加@FormUrlEncoded注解 表示声明表单上传
     * @return
     */
    @FormUrlEncoded
    @POST("?s=App.User.Search")
    Observable<GuoChuangYunBean> getPOSTGuoCHuangYunBean(@FieldMap Map<String ,String > map);

	 /**
     *
     * @param body  POST请求体上传       FormBody app_key = new FormBody.Builder()
     *                                  .add("key", "valye")
     *                                  .build();
     * @return
     */
    @POST("?s=App.User.Search")
    Observable<GuoChuangYunBean> getPOSTBodyGuoCHuangYunBean(@Body RequestBody body);
}

通过Postman请求POST接口,获取参数,在通过GsonFromat获取实体类;

Android网络请求框架(三) Retrofit配合RxJava

获取GuoChuangYunBean实体类:

package demo.ht.com.volley.bean;

import java.util.List;

public class GuoChuangYunBean {

    /**
     * ret : 200
     * data : {"err_code":0,"err_msg":"","users":[]}
     * msg : V3.1.0 YesApi App.User.Search
     */

    private int ret;
    private DataBean data;
    private String msg;

    @Override
    public String toString() {
        return "GuoChuangYunBean{" +
                "ret=" + ret +
                ", data=" + data +
                ", msg='" + msg + '\'' +
                '}';
    }

    public int getRet() {
        return ret;
    }

    public void setRet(int ret) {
        this.ret = ret;
    }

    public DataBean getData() {
        return data;
    }

    public void setData(DataBean data) {
        this.data = data;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public static class DataBean {
        /**
         * err_code : 0
         * err_msg :
         * users : []
         */

        private int err_code;
        private String err_msg;
        private List<?> users;

        @Override
        public String toString() {
            return "DataBean{" +
                    "err_code=" + err_code +
                    ", err_msg='" + err_msg + '\'' +
                    ", users=" + users +
                    '}';
        }

        public int getErr_code() {
            return err_code;
        }

        public void setErr_code(int err_code) {
            this.err_code = err_code;
        }

        public String getErr_msg() {
            return err_msg;
        }

        public void setErr_msg(String err_msg) {
            this.err_msg = err_msg;
        }

        public List<?> getUsers() {
            return users;
        }

        public void setUsers(List<?> users) {
            this.users = users;
        }
    }
}

使用最原始的请求方式请求POST数据:

HashMap<String, String> stringHashMap = new HashMap<>();
        stringHashMap.put("app_key", "74D2E724FE2B69EF7EA3F38E9400CF71");

        FormBody app_key = new FormBody.Builder()
                .add("app_key", "74D2E724FE2B69EF7EA3F38E9400CF71")
                .build();

Retrofit apiServer = new Retrofit.Builder().
                addCallAdapterFactory(RxJava2CallAdapterFactory.create()).
                addConverterFactory(GsonConverterFactory.create())
                .baseUrl(ApiServer.GuoChuangYun_BaseUri)
                .build();


        apiServer.create(ApiServer.class)
                .getPOSTBodyGuoCHuangYunBean(app_key)//@Body注解上传 
//                .getPOSTGuoCHuangYunBean(stringHashMap)//@FormUrlEncoded配合@FieldMap
                .subscribeOn(Schedulers.io())//IO线程
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<GuoChuangYunBean>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(GuoChuangYunBean guoChuangYunBean) {
                      
                        Log.i("szjPOSTonNext","\n"+guoChuangYunBean.toString());
                        mTv.setText("POST接口:\n" + guoChuangYunBean.toString());
                    }

                    @Override
                    public void onError(Throwable e) {

                        mTv.setText("POST接口请求错误:\n" + e.getMessage());
                    }

                    @Override
                    public void onComplete() {

                    }
                });

来康康Log吧:

Android网络请求框架(三) Retrofit配合RxJava

打开本地相册选取图片上传图片

打开本地相册 注意申请动态权限

		//打开本地相册
        Intent intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
        intent.setType("image/png");
        intent.setAction(Intent.ACTION_PICK);
        startActivityForResult(intent, REQUEST_PICTURE_CHOOSE);

重写onActivityResult()方法,获取选取的图片路径,并上传图片

	 @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == REQUEST_PICTURE_CHOOSE) {
            /**
             *  先获取系统返回的图片路径
             *  然后将图片上传,因为这里接口有问题,所以上传不成功!
             */
            Uri selectedImage = data.getData(); //获取系统返回的照片的Uri
            String[] filePathColumn = {MediaStore.Images.Media.DATA};
            Cursor cursor = getContentResolver().query(selectedImage,
                    filePathColumn, null, null, null);//从系统表中查询指定Uri对应的照片
            cursor.moveToFirst();
            int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
            String path = cursor.getString(columnIndex);  //获取照片路径

            Log.i("szjpath", "\t\t" + path);
			//上传图片
            initUpdata(path);
        }
    }

定义接口,设置请求参数:

public interface ApiServer {

		public static String GuoChuangYun_BaseUri = "http://hn216.api.yesapi.cn/";
		
	/**
     *
     * @param body  上传图片
     * @return
     */
	//    @Multipart    注意 : @Multipart 是配合@Part或@PartMap使用的,单独不能使用!!!!!!!
    @POST("?s=App.CDN.UploadImg")
    Observable<ImageBean> getImageBean( @Body RequestBody file);

    /**\
     *
     * @param body  上传的app_key
     * @param file  上传的单张图片
     * @return
     */
    @Multipart
    @POST("?s=App.CDN.UploadImg")
    Observable<ImageBean> uploadFile(@Part("app_key") RequestBody body, @Part MultipartBody.Part file);

}

通过Postman获取数据,并通过GsonFragment获取实体类,这里就不重复写了,和上面步骤一样:

File file = new File(path);

//方法一:
        RequestBody requestBody = new MultipartBody.Builder().
                setType(MultipartBody.FORM)
                .addFormDataPart("app_key", "74D2E724FE2B69EF7EA3F38E9400CF71")
                .addFormDataPart("file", file.getName(), RequestBody.create(MediaType.parse("image/png"), file))
                .build();
                
//方法二:
RequestBody fileRQ = RequestBody.create(MediaType.parse("image/png"), file);
        MultipartBody.Part part = MultipartBody.Part.createFormData("file", file.getName(), fileRQ);
        RequestBody fb =RequestBody.create(MediaType.parse("text/plain"), "74D2E724FE2B69EF7EA3F38E9400CF71");


Retrofit apiServer = new Retrofit.Builder().
                addCallAdapterFactory(RxJava2CallAdapterFactory.create()).
                addConverterFactory(GsonConverterFactory.create())
                .baseUrl(ApiServer.GuoChuangYun_BaseUri)
                .build();
        apiServer.create(ApiServer.class)
//                .getImageBean(requestBody)    //@Body 图片+参数 同时上传
                .uploadFile(requestBody,part)   //@Multipart 配合 @Part 单张图片 和单个参数上传
                .subscribeOn(Schedulers.io())//IO线程
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<ImageBean>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(ImageBean imageBean) {
                        String url = imageBean.getData().getUrl();
                        Glide.with(RetrofitActivity.this)
                                .load(url)
                                .apply(new RequestOptions().placeholder(R.mipmap.ic_launcher))
                                .into(mImage);
                        mTv.setText("图片上传成功:\n" + imageBean.toString());
                        Log.i("szjOnNext", imageBean.toString());
                    }

                    @Override
                    public void onError(Throwable e) {
                        Log.i("onError", e.getMessage());
                        mTv.setText("图片上传失败:\n" + e.getMessage());
                    }

                    @Override
                    public void onComplete() {

                    }
                });

我打开相册上传一张我健身的照片,来康康效果吧:

Android网络请求框架(三) Retrofit配合RxJava

哈哈哈哈哈,献丑了献丑了,还怪不好意思的,羞羞QvQ

@Url使用:

这里拿get接口举例:

public interface ApiServer {
	 @GET
    Observable<MeiNvBean> getUrlMeiNvBean(@Url String url);

}


@Url特别简单,就是传一个完整的接口,通常用于GET请求,没什么难度,就不详细讲解了
Retrofit apiServer = new Retrofit.Builder().
                addCallAdapterFactory(RxJava2CallAdapterFactory.create()).
                addConverterFactory(GsonConverterFactory.create())
                .baseUrl(ApiServer.BaseUri)
                .build();

        apiServer.create(ApiServer.class).getUrlMeiNvBean(ApiServer.BaseUri+"8/1")
                .subscribeOn(Schedulers.io())//IO线程
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<MeiNvBean>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(MeiNvBean meiNvBean) {
                        mTv.setText(meiNvBean.toString());
                        Log.i("szjonNex", meiNvBean.toString());
                    }

                    @Override
                    public void onError(Throwable e) {
                        mTv.setText("请求错误:" + e.getMessage());
                        Log.i("onError", e.getMessage());
                    }

                    @Override
                    public void onComplete() {

                    }
                });

康康所有的效果吧:

Android网络请求框架(三) Retrofit配合RxJava
本篇重复代码比较多,下一篇给大家吧Retrofit封装起来,有想看的同学可以点击查看

Git链接: langyangyang.

写一篇博客实在是太累了,而且还容易写错误导大家,如果有大佬看到有错误的地方,一定请在评论区留言,谢谢大家观看~

本文地址:https://blog.csdn.net/weixin_44819566/article/details/107488575