Retrofit2与RxJava用法大全
Retrofit2是square公司出品的一个网络请求库,网上有很多相关的介绍。我很久以前都想去研究了,但一直都有各种事情耽搁,现在就让我们一起去捋一捋,这篇主要讲解Retrofit2与RxJava的基本用法。
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 添加:
compile 'com.google.code.gson:gson:2.3.1'
compile 'com.squareup.retrofit2:retrofit:2.0.0'
compile 'com.squareup.retrofit2:converter-gson:2.0.0'
compile 'com.squareup.okhttp3:logging-interceptor:3.2.0'
获取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请求
public class SimpleGetActivity extends AppCompatActivity {
    private Button btnGet;
    private TextView tvResult;
    private RestClient mRestClient;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_simple_get);
        btnGet = (Button) findViewById(R.id.btn_get);
        tvResult = (TextView) findViewById(R.id.tv_result);
        btnGet.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //获取实例
                mRestClient = new RestClient();
                Call<ResponseBody> responseBodyCall = mRestClient.getRectService().getManagerData();
                //调用回调接口
                responseBodyCall.enqueue(new Callback<ResponseBody>() {
                    @Override
                    public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                        try {
                            tvResult.setText(response.body().string());
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                    @Override
                    public void onFailure(Call<ResponseBody> call, Throwable t) {
                    }
                });
            }
        });
    }
}
一起来看看效果:
分析返回的 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类:
public class GetActivity extends AppCompatActivity {
    private Button btnGet;
    private RestClient mRestClient;
    private RecyclerView mRecyclerView;
    private BaseRecyclerAdapter<Manager> mAdapter;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_get);
        btnGet = (Button) findViewById(R.id.btn_get);
        mRecyclerView = (RecyclerView) findViewById(R.id.rv);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
        btnGet.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //获取实例
                mRestClient = new RestClient();
                Call<BaseResponse<Manager>> baseResponseCall = mRestClient.getRectService().getManagerDatas();
                baseResponseCall.enqueue(new Callback<BaseResponse<Manager>>() {
                    @Override
                    public void onResponse(Call<BaseResponse<Manager>> call, Response<BaseResponse<Manager>> response) {
                        //获取返回的集合数据
                        //response.body().managerList
                        mAdapter = new BaseRecyclerAdapter<Manager>(GetActivity.this, response.body().managerList, R.layout.rv_item) {
                            @Override
                            protected void convert(BaseViewHolder helper, Manager item) {
                                helper.setText(R.id.tv_item_text, item.UserName);
                            }
                        };
                        mRecyclerView.setAdapter(mAdapter);
                    }
                    @Override
                    public void onFailure(Call<BaseResponse<Manager>> call, Throwable t) {
                    }
                });
            }
        });
    }
}
来看看效果:
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());
        }
    });
看看效果图:
多文件上传
@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[];
            int len;
            while ((len = is.read(buf)) != -) {
                fos.write(buf, , len);
            }
            is.close();
            fos.close();
        } catch (Exception ex) {
        }
    }
}
效果一览:
开启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日志:
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()
.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) { }
});
RxJava支持链式写法,可以处理一些很复杂的问题。
Retrofit2与RxJava用法大全的更多相关文章
- MVC5 + EF6 + Bootstrap3 (9) HtmlHelper用法大全(下)
		
文章来源:Slark.NET-博客园 http://www.cnblogs.com/slark/p/mvc5-ef6-bs3-get-started-httphelper-part2.html 上一节 ...
 - MVC5 + EF6 + Bootstrap3 (8) HtmlHelper用法大全(上)
		
文章来源:Slark.NET-博客园 http://www.cnblogs.com/slark/p/mvc5-ef6-bs3-get-started-httphelper-part1.html 上一节 ...
 - MVC HtmlHelper用法大全
		
MVC HtmlHelper用法大全HtmlHelper用来在视图中呈现 HTML 控件.以下列表显示了当前可用的一些 HTML 帮助器. 本主题演示所列出的带有星号 (*) 的帮助器. ·Actio ...
 - C# MessageBox 用法大全(转)
		
C# MessageBox 用法大全 http://www.cnblogs.com/Tammie/archive/2011/08/05/2128623.html 我们在程序中经常会用到MessageB ...
 - MVC中HtmlHelper用法大全参考
		
MVC中HtmlHelper用法大全参考 解析MVC中HtmlHelper控件7个大类中各个控件的主要使用方法(1) 2012-02-27 16:25 HtmlHelper类在命令System.Web ...
 - pandas用法大全
		
pandas用法大全 一.生成数据表 1.首先导入pandas库,一般都会用到numpy库,所以我们先导入备用: import numpy as np import pandas as pd12 2. ...
 - Retrofit2.0+RxJava+Dragger2实现不一样的Android网络架构搭建
		
Tamic :csdn http://blog.csdn.net/sk719887916 众所周知,手机APP的核心就在于调用后台接口,展示相关信息,方便我们在手机上就能和外界交互.所以APP中网络框 ...
 - Android基于Retrofit2.0 +RxJava 封装的超好用的RetrofitClient工具类(六)
		
csdn :码小白 原文地址: http://blog.csdn.net/sk719887916/article/details/51958010 RetrofitClient 基于Retrofit2 ...
 - 基于Retrofit2.0+RxJava+Dragger2实现不一样的Android网络构架搭建(转载)
		
转载请注明出处:http://blog.csdn.net/finddreams/article/details/50849385#0-qzone-1-61707-d020d2d2a4e8d1a374a ...
 
随机推荐
- linq分页扩展
			
直接上代码了 public static List<T> ToPagedList<T>(this IEnumerable<T> allItems, int page ...
 - mobile web页面调试方法
			
此文已由作者张含会授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 开发过程问题排查 Chrome Emulation关键词:使用方便 模拟各种设备尺寸.像素比.自定义user ...
 - Note: EnclaveDB: A Secure Database using SGX
			
EnclaveDB uses SGX security properties to secure database operations. Why The cloud database is cont ...
 - SpringBoot第五篇:整合Mybatis
			
作者:追梦1819 原文:https://www.cnblogs.com/yanfei1819/p/10869315.html 版权声明:本文为博主原创文章,转载请附上博文链接! 引言 ORM框架 ...
 - Unity 2018中的图形渲染
			
https://mp.weixin.qq.com/s?__biz=MzU5MjQ1NTEwOA==&mid=2247490249&idx=1&sn=d86083e33d9884 ...
 - CF 979D Kuro and GCD and XOR and SUM(异或 Trie)
			
CF 979D Kuro and GCD and XOR and SUM(异或 Trie) 给出q(<=1e5)个操作.操作分两种,一种是插入一个数u(<=1e5),另一种是给出三个数x, ...
 - Jupyter导出PDF从入门到绝望(已解决)
			
Jupyter导出PDF从入门到绝望(已解决) 问题描述 我在使用jupyter lab的时候,想要把我的代码和结果导出成pdf格式的(由于里面有图片,所以不想导出成html).然后报错: 然后我用p ...
 - C# DataTable转List<T>--利用反射
			
/// <summary> /// 利用反射将Datatable转换为List<T>对象 /// </summary> /// <typeparam name ...
 - 分层图 (可以选择K条路的权为0,求最短路)
			
分层图可以处理从图中选取k条边使其边权变为0,求最短路 Description 在你的强力援助下,PCY 成功完成了之前的所有任务,他觉得,现在正是出去浪的大好时光.于是,他来到高速公路上,找到一辆摩 ...
 - Nginx实战(三) 日志配置与切割
			
访问日志主要记录客户端访问Nginx的每一个请求,格式可以自定义.通过访问日志,你可以得到用户地域来源.跳转来源.使用终端.某个URL访问量等相关信息. Nginx中访问日志相关指令主要有两条,一条是 ...