Retrofit2与RxJava用法大全

Retrofit2square公司出品的一个网络请求库,网上有很多相关的介绍。我很久以前都想去研究了,但一直都有各种事情耽搁,现在就让我们一起去捋一捋,这篇主要讲解Retrofit2RxJava的基本用法。

  • 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(49);
                //调用回调接口
                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(49);

                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[1024];
            int len;
            while ((len = is.read(buf)) != -1) {
                fos.write(buf, 0, 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(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) {

            }
        });

RxJava支持链式写法,可以处理一些很复杂的问题。

源码地址

原文地址:https://www.cnblogs.com/zhujiabin/p/9246415.html

时间: 2024-10-27 03:14:51

Retrofit2与RxJava用法大全的相关文章

Delphi ListView基本用法大全[delphi]

Delphi ListView基本用法大全 本文出处:http://hi.baidu.com/python120/item/4ea85f61af94e55b6895e6ac //增加项或列(字段) ListView1.Clear;ListView1.Columns.Clear;ListView1.Columns.Add;ListView1.Columns.Add;ListView1.Columns.Add;ListView1.Columns.Items[0].Caption:='id';List

NSString 用法大全。

一.NSString 创建字符串.  NSString *astring = @"This is a String!"; 创建空字符串,给予赋值.  NSString *astring = [[NSString alloc] init]; astring = @"This is a String!"; NSLog(@"astring:%@",astring); string release]; 使用变量初始化  NSString *name = 

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用法大全(上) 源码下载:点我下载 目录: 说明 Form表单 使用TagBuilder创建自定义标签 强类型HtmlHelper LabelFor数据标签 DisplayFor 和 EditorFor显示和编辑Model

Retrofit2.0+ RxJava 优雅的取消重复避免并取消请求(十一)

Tamic/文 地址:http://blog.csdn.net/sk719887916/article/details/54575137 前几篇主要介绍了retrofit基本使用,结合rxJava的案列,以及RxJava结合retrofit的封装,包括公用参数,局部参数请求头添加,缓存,https, 文件上下传,结果解析,异常处理等,还有一些技巧,那么还有一个比较关键的是取消问题. 两者结合技巧可点击阅读:http://blog.csdn.net/sk719887916/article/deta

TXT文件用法大全【荐】

来源:全文链接 (3)读取TXT文件指定某一行的第?到第?个字 UserVar t=2 "读出txt第几行文本" UserVar i=5 "从第几个字开始读取" UserVar O=8 "结束读取到第几个字" Text = Plugin.File.ReadFileEx("路径\文件名.txt") txtArray=Split(Text,"|") I=I-1 O=O-I:T=T-1 For O str=str

基于Retrofit2.0+RxJava+Dragger2实现不一样的Android网络构架搭建(转载)

转载请注明出处:http://blog.csdn.net/finddreams/article/details/50849385#0-qzone-1-61707-d020d2d2a4e8d1a374a433f596ad1440   一起分享,一起进步.finddreams:http://blog.csdn.net/finddreams/article/details/50849385 众所周知,手机APP的核心就在于调用后台接口,展示相关信息,方便我们在手机上就能和外界交互.所以APP中网络框架

c#正则表达式用法大全

c#正则表达式用法大全  只能输入数字:"^[0-9]*$". 只能输入n位的数字:"^\d{n}$". 只能输入至少n位的数字:"^\d{n,}$". 只能输入m~n位的数字:."^\d{m,n}$" 只能输入零和非零开头的数字:"^(0|[1-9][0-9]*)$". 只能输入有两位小数的正实数:"^[0-9]+(.[0-9]{2})?$". 只能输入有1~3位小数的正实数:&quo

Retrofit2.0+RxJava+RxAndroid——强强联合的网络请求框架

最近看了很多关于Retrofit和Rxjava的文档介绍.终于在弄清Rxjava后顺利的弄懂了Retrofit. 网上有很多人都介绍了它们的联合使用,但是我看过之后理解不是太好.可能我太笨. 不过,今天写这篇博客的目的就是想来说说它们之间如何使用以及使用的时候遇到的坑. 这两者的关系并不大,但是联合在一起使用是非常简便的.Rxjava的响应式编程加上Retrofit的注解式请求用起来是非常爽的. 并且Retrofit内置的是Okhttp,所以这更加的让Retrofit变得强大. 如果在看这篇博客

c++中const用法大全

 1. const 修饰普通变量 const修饰一个变量,意思就是这个变量是一个常量,不能被改变 const int x;              //x是一个整形常量 const double x;        //x 是一个double型常量 const 修饰的是一个指针时: const int *x;          //x 是一个指向常量整形的指针 int *const x:        //x 是一个常量指针. const int *const x ;          /