rxjava2+retrofit2 简介

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: rxjava2+retrofit2 简介

简述



Retrofit2square公司出品的一个网络请求库,网上有很多相关的介绍。


  • get请求
  • post请求
  • 文件上传
  • 文件下载
  • 开启日志拦截
  • 与RxJava结合使用


什么是Retrofit2



官网是这么介绍的:


Retrofit adapts a Java interface to HTTP calls by using annotations on the declared methods to 
define how requests are made。

他的大概意思是说:Retrofit 是一个 java 接口类,以注解的方式用于 HTTP 网络请求。


使用前的配置



build.gradle 的 dependencies 添加:


获取Retrofit实例



Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("http://plus31.366ec.net/")
    .addConverterFactory(GsonConverterFactory.create())
    .build();

需要注意的是baseUrl添加的是地址的主域名。


申明RestService接口类


public interface RestService {
    @GET("/Route.axd?method=vast.Store.manager.list")
    Call<ResponseBody> getManagerData(@Query("StoreId") int id);
}

@GET 包含的是请求地址,是主域名之后的地址。举个例子,请求的

全地址:http://plus31.366ec.net/Route.axd?method=vast.Store.manager.list

主域名为:http://plus31.366ec.net/

@GET包含的地址为:/Route.axd?method=vast.Store.manager.list

这样就完成了一个简单的@GET封装。


创建RestClient类



public class RestClient {
    private Retrofit mRetrofit;
    private static final String BASE_URL = "http://plus31.366ec.net/";
    private RestService mService;
    //构造方法
    public RestClient() {
        mRetrofit = new Retrofit.Builder()
                .baseUrl(BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        mService = mRetrofit.create(RestService.class);
    }
    public RestService getRectService() {
        if (mService != null) {
            return mService;
        }
        return null;
    }
}

这样就生成了一个简单的代理类,然后就可以进行相应请求了。


Get请求



一起来看看效果:


cbee22012e3f4e1ba93b19f777fa8550_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.png


分析返回的 json数据,包含集合,那么我们可以进一步对接口返回值进行数据的封装。


BaseResponse类


public class BaseResponse<T> {
    @SerializedName("data")
    public List<T> managerList;
    @SerializedName("code")
    public int code;
    @SerializedName("message")
    public String message;
}

注意:BaseResponse类的字段,根据自己返回json数据新增或者删除。

根据返回的json集合,那么我们肯定有个实体类了。


Manager类


public class Manager {
    public int Id;
    public String UserName;
}

Manager 类你可以替换成你自己的实体类。


Get的进一步封装


@GET("/Route.axd?method=vast.Store.manager.list")
Call<BaseResponse<Manager>> getManagerDatas(@Query("StoreId") int id);

注意:我们这里对方法的返回值进行了一个修改Call<BaseResponse<Manager>>

来看看封装后的Activity类:


来看看效果:


0c0d35fbe86f40ecbea25be3a8787cc5_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.gif


Get常用技巧


HashMap组装参数


@GET("/Route.axd?method=vast.Store.manager.list")
    Call<BaseResponse<Manager>> getManagerDatas(@QueryMap HashMap<String, String> hm);

Get 请求就讲到这里了,下面一起来看看 Post请求。


Post请求



@FormUrlEncoded
    @POST("/Route.axd?method=vast.Store.manager.list")
    Call<BaseResponse<Manager>> postManagerDatas(@Field("StoreId") int id);

@Field("StoreId") int id可以替换@Body@Body你可以传入HashMap、实体 beans 等对象。


注意:以@Body上传参数,会默认加上Content-Type: application/json;charset=UTF-8的请求头,即以JSON格式请求,再以JSON格式响应。


单个文件上传



@Multipart
    @POST("/UploadProduct.axd")
    Call<ResponseBody> uploadSimpleFile(@Part MultipartBody.Part file);

文件上传稍微复杂点,具体请看以下代码:


File file = new File("/sdcard/", "a.xlxs");
    //file
    RequestBody requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), file);
    //监听上传进度
    CountingRequestBody countingRequestBody = new CountingRequestBody(requestFile, new CountingRequestBody.Liste
        @Override
        public void onRequestProgress(long bytesWritten, long contentLength) {
            tvFile.setText("上传进度:" + contentLength + ":" + bytesWritten);
        }
    });
    MultipartBody.Part body =
            MultipartBody.Part.createFormData("file", file.getName(),countingRequestBody);
    mRestClient = new RestClient("http://192.168.4.111:686/");
    Call<ResponseBody> responseBodyCall = mRestClient.getRectService().uploadSimpleFile(body);
    responseBodyCall.enqueue(new Callback<ResponseBody>() {
        @Override
        public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
            tvFile.setText("上传成功");
        }
        @Override
        public void onFailure(Call<ResponseBody> call, Throwable t) {
            tvFile.setText(t.toString());
        }
    });

看看效果图:


a3ee45e1c4be45259bb2ff59153a7d4b_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.gif


多文件上传



@Multipart
@POST("/HpWens/ProgressDemos/")
Call<ResponseBody> uploads(@PartMap Map<String, RequestBody> params);

private void initData() {
        //保证文件按顺序上传 使用LinkedHashMap
        params = new LinkedHashMap<>();
        File file1 = new File("/sdcard/", "a.xlxs");
        final RequestBody requestBody1 = RequestBody.create(MediaType.parse("multipart/form-data"), file1);
        //监听上传进度
        CountingRequestBody countingRequestBody1 = new CountingRequestBody(requestBody1, new CountingRequestBody.Listener() {
            @Override
            public void onRequestProgress(long bytesWritten, long contentLength) {
                tvFile1.setText("上传进度:" + contentLength + ":" + bytesWritten);
            }
        });
        params.put("file";filename="" + file1.getName(), countingRequestBody1);
        File file2 = new File("/sdcard/", "a.xlxs");
        RequestBody requestBody2 = RequestBody.create(MediaType.parse("multipart/form-data"), file2);
        //监听上传进度
        CountingRequestBody countingRequestBody2 = new CountingRequestBody(requestBody2, new CountingRequestBody.Listener() {
            @Override
            public void onRequestProgress(long bytesWritten, long contentLength) {
                tvFile2.setText("上传进度:" + contentLength + ":" + bytesWritten);
            }
        });
        params.put("file";filename="" + file2.getName(), countingRequestBody2);
        mRestClient = new RestClient("http://192.168.4.111:686/");
        btnUpload.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Call<ResponseBody> responseBodyCall = mRestClient.getRectService().uploadMultiFiles(params);
                responseBodyCall.enqueue(new Callback<ResponseBody>() {
                    @Override
                    public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                        tvFile1.setText("上传成功");
                        tvFile2.setText("上传成功");
                    }
                    @Override
                    public void onFailure(Call<ResponseBody> call, Throwable t) {
                    }
                });
            }
        });
    }

在文章的后面我会附上源码,这里我就不在贴图了,具体请看demo


文件下载



@Streaming
@GET("/image/h%3D360/sign=86aee1fbf1deb48fe469a7d8c01e3aef/{filename}")
Call<ResponseBody> downFile(@Path("filename") String fileName);

处理方式基本和上面几种差不多:


public class DownFileActivity extends AppCompatActivity {
    private ImageView iv;
    private Button btnDown;
    private RestClient mRestClient;
    private String fileName;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_down_file);
        iv = (ImageView) findViewById(R.id.iv);
        btnDown = (Button) findViewById(R.id.btn_down);
        mRestClient = new RestClient("http://d.hiphotos.baidu.com/");
        fileName = "b812c8fcc3cec3fd8757dcefd488d43f8794273a.jpg";
        btnDown.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Call<ResponseBody> userCall = mRestClient.getRectService().downFile(fileName);
                userCall.enqueue(new Callback<ResponseBody>() {
                    @Override
                    public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                        iv.setImageBitmap(BitmapFactory.decodeStream(response.body().byteStream()));
                        //saveFile(response.body().byteStream());
                    }
                    @Override
                    public void onFailure(Call<ResponseBody> call, Throwable t) {
                    }
                });
            }
        });
    }
    public void saveFile(InputStream is){
        try {
            String fn = Environment.getExternalStorageDirectory() + "/" + fileName;
            FileOutputStream fos = new FileOutputStream(fn);
            byte[] buf = new byte[1024];
            int len;
            while ((len = is.read(buf)) != -1) {
                fos.write(buf, 0, len);
            }
            is.close();
            fos.close();
        } catch (Exception ex) {
        }
    }
}

效果一览:


84e7713b6dd94e83a1695376ed62f9f1_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.gif


开启OKHttp的日志拦截



开启日志后,会记录request和response的相关信息,非常实用,也非常强大,不知道是否是编码格式,我下载图片打印的全是乱码。


public void initRestClint(String baseUrl) {
    logging.setLevel(HttpLoggingInterceptor.Level.BODY);
    OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
    httpClient.addInterceptor(logging);
    mRetrofit = new Retrofit.Builder()
            .baseUrl(baseUrl)
            .addConverterFactory(GsonConverterFactory.create())
            .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
            .client(httpClient.build())
            .build();
    mService = mRetrofit.create(RestService.class);
}

类似这样的logcat日志:


df00de579f2f43249e3a896809e0b12a_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.png


Retrofit2与RxJava结合使用



添加库:


compile 'io.reactivex:rxandroid:1.1.0'
    compile 'com.squareup.retrofit2:adapter-rxjava:2.0.0'

添加addCallAdapterFactory(RxJavaCallAdapterFactory.create())Retrofit.Builder中:


mRetrofit = new Retrofit.Builder()
        .baseUrl(baseUrl)
        .addConverterFactory(GsonConverterFactory.create())
        .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
        .client(httpClient.build())
        .build();

那么我们结合RxJava一起使用呢,下面我们一起来看一看:


@GET("/Route.axd?method=vast.Store.manager.list")
Observable<BaseResponse<Manager>> getManagers(@Query("StoreId") int id);

通过我们的观察是不是发现只有返回值发送了变化,Observable类型。


//获取实例
mRestClient = new RestClient();
mRestClient.getRectService().getManagers(49)
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new Subscriber<BaseResponse<Manager>>() {
            @Override
            public void onCompleted() {
            }
            @Override
            public void onError(Throwable e) {
            }
            @Override
            public void onNext(BaseResponse<Manager> managerBaseResponse) {
            }
        });



相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
4月前
retrofit+okhttp+rxjava
retrofit+okhttp+rxjava
|
6月前
|
JSON Java 数据格式
rxjava2+retrofit2
rxjava2+retrofit2
51 1
|
JSON 安全 Java
Retrofit入门
Retrofit入门
|
JSON Android开发 数据格式
RxJava+Retrofit示例 ,Retrofit 注解学习
RxJava+Retrofit示例 ,Retrofit 注解学习
170 0
|
Java Android开发
关于Rxjava的简单使用
本篇只是讲一下Rxjava的简单入门使用,想要详解的请移步其他博主文章,关于RxJava详解的文章网上一大堆,本片文章内容适合小白学习。
167 1
|
Java 数据库 UED
RxJava的简介
RxJava的简介
298 0
RxJava的简介
|
JSON Android开发 数据格式
使用Retrofit + RxJava 网络请求
使用Retrofit + RxJava 网络请求
392 0
使用Retrofit + RxJava 网络请求
|
API Android开发 Java
RxJava2 和 Retrofit2 结合使用详解
不讲 rxjava 和 retrofit 而是直接上手 2 了,因为 2 封装的更好用的更多。 1. 观察者模式 常见的 button 点击事件为例,button 是被观察者,listener 是观察者,setOnClickListener 过程是订阅,有了订阅关系后在 button 被点击的时候,监听者 listener 就可以响应事件。
|
JSON Java API
|
缓存 JSON API
一款基于RxJava2+Retrofit2实现简单易用的网络请求框架
本库是一款基于RxJava2+Retrofit2实现简单易用的网络请求框架,结合android平台特性的网络封装库,采用api链式调用一点到底,集成cookie管理,多种缓存模式,极简https配置,上传下载进度显示,请求错误自动重试,请求携带token、时间戳、签名sign动态配置,自动登录成功后请求重发功能,3种层次的参数设置默认全局局部,默认标准ApiResult同时可以支持自定义的数据结构,已经能满足现在的大部分网络请求。
2629 0