zoukankan      html  css  js  c++  java
  • 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) {
    
                        }
                    });
                }
            });
        }
    }

    一起来看看效果:

    retro


    分析返回的 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) {
    
                        }
                    });
    
                }
            });
        }
    }

    来看看效果:

    retro


    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());
            }
        });

    看看效果图:

    retro

    多文件上传

    @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) {
    
            }
        }
    }

    效果一览:

    retro


    开启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日志:

    retro

    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支持链式写法,可以处理一些很复杂的问题。

    源码地址

  • 相关阅读:
    【网络】默认路由(路由黑洞,路由终结)
    textstroke(文本描边)和textfillcolor(文本填充色)Css3演示
    enter键提交表单
    Web App和Native App 谁将是未来
    模拟input type=file
    margintop 无效,避开麻烦的margin叠加(margin collapsing)
    用jquery写的简单tab效果
    CSS3下的渐变文字效果实现
    jQuery阻止冒泡和HTML默认操作
    设置文本输入框默认值
  • 原文地址:https://www.cnblogs.com/zhujiabin/p/9246415.html
Copyright © 2011-2022 走看看