GVKun编程网logo

如何进行多个请求并等待数据来自retrofit 2.0中的所有请求 – android(android什么意思)

9

在本文中,我们将带你了解如何进行多个请求并等待数据来自retrofit2.0中的所有请求–android在这篇文章中,我们将为您详细介绍如何进行多个请求并等待数据来自retrofit2.0中的所有请求

在本文中,我们将带你了解如何进行多个请求并等待数据来自retrofit 2.0中的所有请求 – android在这篇文章中,我们将为您详细介绍如何进行多个请求并等待数据来自retrofit 2.0中的所有请求 – android的方方面面,并解答android什么意思常见的疑惑,同时我们还将给您一些技巧,以帮助您实现更有效的Android OkHttp + Retrofit 取消请求的方法、android retrofit 请求参数格式RequestBody的方法、android retrofit 请求返回String数据中文乱码解决方案、android Retrofit2网络请求封装介绍

本文目录一览:

如何进行多个请求并等待数据来自retrofit 2.0中的所有请求 – android(android什么意思)

如何进行多个请求并等待数据来自retrofit 2.0中的所有请求 – android(android什么意思)

当前代码:

Retrofit retrofit = new Retrofit.Builder()
                  .baseUrl(Constant.BASEURL)
                  .addConverterFactory(GsonConverterFactory.create())
                  .build();

APIService service = retrofit.create(APIService.class);

Call<ResponseWrap> call = service.getNewsData();

call.enqueue(new Callback<ResponseWrap>() {

  @Override
  public void onResponse(Call<ResponseWrap> call1, Response<ResponseWrap> response) {
    if (response.isSuccess()) {

        ResponseWrap finalRes = response.body();
        for(int i=0; i<finalRes.getResponse().getResults().size(); ++i){
            String title = finalRes.getResponse().getResults().get(i).getWebTitle();
            News n = new News(titleCategory, title, null);
            newsList.add(n);
        }

        AdapterRecommendation adapter = new AdapterRecommendation(getApplicationContext(), newsList);
        listView.setAdapter(adapter);

    }
    else{
        Toast.makeText(getApplicationContext(), "onResponse  - something wrong" + response.message(), Toast.LENGTH_LONG).show();
    }
  }

  @Override
  public void onFailure(Call<ResponseWrap> call1, Throwable t) {
      Toast.makeText(getApplicationContext(), "exception: " + t.getMessage(), Toast.LENGTH_LONG).show();
  }
});

工作正常.

现在我想进行多次呼叫(呼叫次数将在运行时决定),所有呼叫都以相同的格式提供数据.所有调用的数据都需要添加到newsList中.一旦所有呼叫都有数据并添加到newsList,请致电

AdapterRecommendation adapter = new AdapterRecommendation(getApplicationContext(), newsList);
listView.setAdapter(adapter);

任何人都可以帮助我从多个调用中获取数据的最佳方法是什么,并等待所有请求在改进2.0中没有结束.

解决方法:

等待所有请求完成的干净利落的方法是将Retrofit2与RxJava2及其zip函数结合使用.

zip的作用基本上是构造新的observable,等待所有改进的Observable请求完成然后它将发出自己的结果.

以下是Observables的Retrofit2接口示例:

public interface MyBackendAPI {
  @GET("users/{user}")
  Observable<User> getUser(@Path("user") String user);

  @GET("users/{user}/photos")
  Observable<List<Photo>> listPhotos(@Path("user") String user);

  @GET("users/{user}/friends")
  Observable<List<User>> listFriends(@Path("user") String user);
}

在您要发出多个请求的代码中,只有在所有请求完成后才能执行其他操作,然后您可以编写以下内容:

    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl("https://api.example.com/")
            .build();

    MyBackendAPI backendApi = retrofit.create(MyBackendAPI.class);

    List<Observable<?>> requests = new ArrayList<>();

    // Make a collection of all requests you need to call at once, there can be any number of requests, not only 3. You can have 2 or 5, or 100.
    requests.add(backendApi.getUser("someUserId"));
    requests.add(backendApi.listPhotos("someUserId"));
    requests.add(backendApi.listFriends("someUserId"));

    // Zip all requests with the Function, which will receive the results.
    Observable.zip(
            requests,
            new Function<Object[], Object>() {
                @Override
                public Object apply(Object[] objects) throws Exception {
                    // Objects[] is an array of combined results of completed requests

                    // do something with those results and emit new event
                    return new Object();
                }
            })
            // After all requests had been performed the next observer will receive the Object, returned from Function
            .subscribe(
                    // Will be triggered if all requests will end successfully (4xx and 5xx also are successful requests too)
                    new Consumer<Object>() {
                        @Override
                        public void accept(Object o) throws Exception {
                            //Do something on successful completion of all requests
                        }
                    },

                    // Will be triggered if any error during requests will happen
                    new Consumer<Throwable>() {
                        @Override
                        public void accept(Throwable e) throws Exception {
                            //Do something on error completion of requests
                        }
                    }
            );

就这样 :)

以防万一在Kotlin中显示相同的代码是什么样的.

    val retrofit = Retrofit.Builder()
            .baseUrl("https://api.example.com/")
            .build()

    val backendApi = retrofit.create(MyBackendAPI::class.java)

    val requests = ArrayList<Observable<*>>()

    requests.add(backendApi.getUser())
    requests.add(backendApi.listPhotos())
    requests.add(backendApi.listFriends())

    Observable
            .zip(requests) {
                // do something with those results and emit new event
                Any() // <-- Here we emit just new empty Object(), but you can emit anything
            }
            // Will be triggered if all requests will end successfully (4xx and 5xx also are successful requests too)
            .subscribe({
                //Do something on successful completion of all requests
            }) {
                //Do something on error completion of requests
            }

Android OkHttp + Retrofit 取消请求的方法

Android OkHttp + Retrofit 取消请求的方法

本文链接

前言

在某一个界面,用户发起了一个网络请求,因为某种原因用户在网络请求完成前离开了当前界面,比较好的做法是取消这个网络请求。对于OkHttp来说,具体是调用Callcancel方法。

如何找到这一个网络请求并取消掉它呢?

操作大致分为3步。第一步,在建立请求时,给请求(request)添加标记;第二步,根据标记,找到请求;最后,取消这个请求。

OkHttp中的tag

要取消一个请求,OkHttp中可以使用cancel方法,参考。

OkHttp的request对象有tag。可以根据tag来标示请求。参考Stack Overflow。

    //Set tags for your requests when you build them:
    Request request = new Request.Builder().
    url(url).tag("requestKey").build();

    //When you want to cancel:
    //A) go through the queued calls and cancel if the tag matches:
    for (Call call : mHttpClient.dispatcher().queuedCalls()) {
        if (call.request().tag().equals("requestKey"))
            call.cancel();
    }

    //B) go through the running calls and cancel if the tag matches:
    for (Call call : mHttpClient.dispatcher().runningCalls()) {
        if (call.request().tag().equals("requestKey"))
            call.cancel();
    }

Retrofit中并没有显示地提供取消请求的接口。2018年时Retrofit仍未提供直接访问call对象的方法
那么如何找到目标网络请求呢?

Retrofit加入自定义header

给每个与页面(Activity,Fragment)相关的request加入自定义header,参考。
给OkHttpClient添加拦截器。标记出页面的生存状态。如果页面销毁了,则取消对应的request。

以GithubOnAndroid项目为例,https://github.com/RustFisher/GithubOnAndroid

添加标记

持有一个ConcurrentHashMap<String, Boolean>来标记页面存活状态。

    private static ConcurrentHashMap<String, Boolean> actLiveMap = new ConcurrentHashMap<>(); // 标记Activity是否存活

    public static void markPageAlive(String actName) {
        actLiveMap.put(actName, true);
    }

    public static void markPageDestroy(String actName) {
        actLiveMap.put(actName, false);
    }

Activity中登记界面状态

给当前Activity起名字。每个Activity的标记名必须唯一。

private static final String MY_ACT_NAME = "xxx1Activity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        NetworkCenter.markPageAlive(MY_ACT_NAME);
        // ...
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        NetworkCenter.markPageDestroy(MY_ACT_NAME);
        // ...
    }

OkHttpClient添加拦截器

给OkHttpClient添加拦截器,在拦截器中检查页面的存活情况。
检查后,把这个自定义header移除掉。

    public static final String HEADER_ACT_NAME = "Activity-Name"; // 标记Activity界面名字

    private Interceptor lifeInterceptor = new Interceptor() {
        @Override
        public Response intercept(Chain chain) throws IOException {
            Request request = chain.request();
            String actName = request.header(HEADER_ACT_NAME);
            if (!TextUtils.isEmpty(actName)) {
                Log.d(TAG, "lifeInterceptor: actName: " + actName);
                Boolean actLive = actLiveMap.get(actName);
                if (actLive == null || !actLive) {
                    chain.call().cancel();
                    Log.d(TAG, "lifeInterceptor: 取消请求, actName: " + actName);
                } else {
                    Log.d(TAG, "lifeInterceptor: 发起请求, actName: " + actName);
                }
            }
            Request newRequest = request.newBuilder().removeHeader(HEADER_ACT_NAME).build();
            return chain.proceed(newRequest);
        }
    };


OkHttpClient = new OkHttpClient.Builder()
        .readTimeout(10, TimeUnit.SECONDS)
        .connectTimeout(10, TimeUnit.SECONDS)
        .addInterceptor(lifeInterceptor) // 添加拦截器
        .build();

call.cancel()后,不会再走Retrofit的subscribe方法。

添加header

    @GET("users/{owner}/repos")
    Observable<List<UserRepo>> userRepo(
            @Header(NetworkCenter.HEADER_ACT_NAME) @Nullable String actName,
            @Path("owner") String owner,
            @Query("sort") String sortType);

android retrofit 请求参数格式RequestBody的方法

android retrofit 请求参数格式RequestBody的方法

以前都是使用

Observable<ResponseBody> login(@HeaderMap Map<String, String> headers, @QueryMap Map<String, String> map);

@QueryMap方式,将参数放入map中传输的

现在改用RequestBody的方式

Observable<ResponseBody> login(@HeaderMap Map<String, String> headers, @Body RequestBody requestBody);

那么如何转换呢,很简单,只需要把以前的map封装一下即可得到RequestBody作为参数了

import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.Request;
import okhttp3.RequestBody;

 

/**
 * 将map数据转换为 普通的 json RequestBody
 * @param map 以前的请求参数
 * @return
 */
public static RequestBody convertMapToBody(Map<?,?> map) {
    return RequestBody.create(MediaType.parse("application/json; charset=utf-8"), new JSONObject(map).toString());
}

/**
 * 将map数据转换为图片,文件类型的  RequestBody
 * @param map 以前的请求参数
 * @return 待测试
 */
public static RequestBody convertMapToMediaBody(Map<?,?> map) {
    return RequestBody.create(MediaType.parse("multipart/form-data; charset=utf-8"), new JSONObject(map).toString());
}

 

android retrofit 请求返回String数据中文乱码解决方案

android retrofit 请求返回String数据中文乱码解决方案

问题来源

focus 应用中核心的部分是,网络请求订阅的xml文件内容,然后解析xml文件存储到本地数据库。

这里网络请求我使用的是retrofit,返回的类型是String,所以使用的是ScalarsConverterFactory的解析器。

*就会出现中文乱码问题。

 

解决方法

 

给okhttp添加拦截器

EncodingInterceptor.java

package com.ihewro.focus.helper;

import com.blankj.ALog;
import com.ihewro.focus.util.StringUtil;

import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.net.SocketTimeoutException;
import java.util.logging.Logger;

import okhttp3.Headers;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;

/**
 * <pre>
 *     time   : 2019/05/23
 *     desc   :
 *     version: 1.0
 * </pre>
 */
public class EncodingInterceptor implements Interceptor {


    /**
     * 自定义编码
     */
    private String encoding;

    public EncodingInterceptor(String encoding) {
        this.encoding = encoding;
    }

    @Override public Response intercept(Interceptor.Chain chain) throws IOException {
        Request request = chain.request();
        Response response = chain.proceed(request);

        settingClientCustomEncoding(response);
        return response;
    }

    /**
     * setting client custom encoding when server not return encoding
     * @param response
     * @throws IOException
     */
    private void settingClientCustomEncoding(Response response) throws IOException {
        setBodyContentType(response);

    }
    

    /**
     * set body contentType
     * @param response
     * @throws IOException
     */
    private void setBodyContentType(Response response) throws IOException {
        ResponseBody body = response.body();
        // setting body contentTypeString using reflect
        Class<? extends ResponseBody> aClass = body.getClass();
        try {
            Field field = aClass.getDeclaredField("contentTypeString");
            field.setAccessible(true);
            String contentTypeString = String.valueOf(field.get(body));
            field.set(body, "application/rss+xml;charset=" + encoding);

        } catch (NoSuchFieldException e) {
            throw new IOException("use reflect to setting header occurred an error", e);
        } catch (IllegalAccessException e) {
            throw new IOException("use reflect to setting header occurred an error", e);
        }
    }

}

然后在okhttp里面拦截一下:

 
 builder.addInterceptor(new EncodingInterceptor("ISO-8859-1"));//全部转换成这个编码
说明一下为什么全部转换成这个编码ISO-8859-1,(对全部转换,听我的,全部听我的) 因为这个编码可以后面再无损的转换成gbk或者utf-8。相反gbk和utf-8编码直接是无法转换的。

然后获取到response.body 之后,再进行对内容编码转换。

        //获取xml文件的编码
        String encode = "UTF-8";//默认编码
        String originCode = "ISO-8859-1";
        String temp = xmlStr.substring(0,100);
        Pattern p = Pattern.compile("encoding=\"(.*?)\"");
        Matcher m = p.matcher(temp);
        boolean flag = m.find();//【部分匹配】,返回true or false,而且指针会移动下次匹配的位置
        if (flag){
            int begin = m.start()+10;
            int end = m.end();
            encode = temp.substring(begin,end-1);
            ALog.d("编码:"+encode);
        }//否则就是文件没有标明编码格式,按照utf-8进行解码


        //如果文件没有乱码,则不需要转换(为什么需要这部分后面分析会写到)
        if (!java.nio.charset.Charset.forName("GBK").newEncoder().canEncode(xmlStr.substring(0,Math.min(xmlStr.length(),3000)))){
            xmlStr = new String(xmlStr.getBytes(originCode),encode);
        }else {
        }
 

为什么会乱码

正常的网页返回的时候会有一个返回头信息:

 

里面会标明返回字符串的编码。

有的网页不仅不返回这个编码信息,而且使用gbk编码。这retrofit就默认按照utf-8编码进行读取字符串了。

具体retrofit的执行流程如下:

//业务代码,同步请求
call.execute();

//跳转 retrofit2.OkHttpCall#execute
 @Override public Response<T> execute() throws IOException {
    okhttp3.Call call;

    ...(对call的处理)

    return parseResponse(call.execute());
  }

可以看到对请求是两步处理了:

okhttp3.Response = call.execute()

parseResponse(okhttp3.Response)

我们先分析call.execute()


//okhttp3.RealCall#execute

@Override public Response execute() throws IOException {

...
      Response result = getResponseWithInterceptorChain();
...   
}
  
  //okhttp3.RealCall#getResponseWithInterceptorChain
  Response getResponseWithInterceptorChain() throws IOException {
    // Build a full stack of interceptors.
    ...
    return chain.proceed(originalRequest);
  }

后面的proceed根据okhttp一开始绑定的拦截器,进行链式处理服务器返回的内容。

public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec,
    
    ...
    
    Interceptor interceptor = interceptors.get(index);
    Response response = interceptor.intercept(next);
    
    ...
 
    return response;
  }

我使用了com.squareup.okhttp3:logging-interceptor:3.4.1用来打印请求信息,所以会有下面的处理:

//okhttp3.logging.HttpLoggingInterceptor#intercept
@Override public Response intercept(Chain chain) throws IOException {
    
    ...
        
    Charset charset = UTF8;
    MediaType contentType = requestBody.contentType();
    if (contentType != null) {
        charset = contentType.charset(UTF8);
    }
    
    ...
    
    return response;
  }
  
  //okhttp3.MediaType#charset(java.nio.charset.Charset)
    public @Nullable Charset charset(@Nullable Charset defaultValue) {
    try {
      return charset != null ? Charset.forName(charset) : defaultValue;
    } catch (IllegalArgumentException e) {
      return defaultValue; // This charset is invalid or unsupported. Give up.
    }
  }

其中requestBody.contentType(),就是根据服务器返回的header中的content-Type字段(如:content-type: text/html; charset=UTF-8)获取到结果编码。

如果这个字段中没有注明charset,则默认设置为utf-8

关于contentType() 函数 如何从content-Type字段获取到编码信息的,可以看下面的源码:

 

contentType()源码分析
 

 

至于第二步的parseResponse是根据第一步的处理结果进一步处理(比如根据状态码,不同处理等)。与问题无关则不再分析。

//retrofit2.OkHttpCall#parseResponse
  Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
    ResponseBody rawBody = rawResponse.body();

    rawResponse = rawResponse.newBuilder()
        .body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
        .build();

    ...(请求结束的后续处理)
  }  

按照上面分析,我们只需要在一开始的拦截器,将服务器的contentTypeString,修改为编码为ISO-8859-1,然后再根据xml文件的encoding字段标明的编码重新编码即可。

但是仍然有一种情况下会出现乱码:

服务器中content-type字段包含utf-8编码信息,按照上面先转ISO-8858-1编码,再转回来,仍然乱码了。

经过debug,发现虽然设置ISO-8858-1的content-type字段,但是结果仍然是utf-8编码,这样的话按照ISO-8858-1解码再UTF-8编码一次就会出现乱码。

所以为什么结果在未二次编码前不是ISO-8858-1编码,而自动变成了utf-8编码了呢?


这一切要从parseResponse()函数,我们前面忽略的部分说起,因为这类编码器正是在这个函数中开始工作的:

  Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
    ResponseBody rawBody = rawResponse.body();

    // Remove the body''s source (the only stateful object) so we can pass the response along.
    rawResponse = rawResponse.newBuilder()
        .body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
        .build();

   ...

    ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody(rawBody);
    try {
      T body = responseConverter.convert(catchingBody);
      return Response.success(body, rawResponse);
    } catch (RuntimeException e) {
      catchingBody.throwIfCaught();
      throw e;
    }
  }

我们使用的ScalarResponseBodyConverter太智能了,它能根据服务器数据的字节流判断是否是utf系列编码


//retrofit2.converter.scalars.ScalarResponseBodyConverters.StringResponseBodyConverter#convert
@Override public String convert(ResponseBody value) throws IOException {
      return value.string();
}

//okhttp3.ResponseBody#string
  public final String string() throws IOException {
    BufferedSource source = source();
    try {
      Charset charset = Util.bomAwareCharset(source, charset());
      return source.readString(charset);
    } finally {
      Util.closeQuietly(source);
    }
  }
  

//okhttp3.internal.Util#bomAwareCharset
  public static Charset bomAwareCharset(BufferedSource source, Charset charset) throws IOException {
    if (source.rangeEquals(0, UTF_8_BOM)) {
      source.skip(UTF_8_BOM.size());
      return UTF_8;
    }
    if (source.rangeEquals(0, UTF_16_BE_BOM)) {
      source.skip(UTF_16_BE_BOM.size());
      return UTF_16_BE;
    }
    if (source.rangeEquals(0, UTF_16_LE_BOM)) {
      source.skip(UTF_16_LE_BOM.size());
      return UTF_16_LE;
    }
    if (source.rangeEquals(0, UTF_32_BE_BOM)) {
      source.skip(UTF_32_BE_BOM.size());
      return UTF_32_BE;
    }
    if (source.rangeEquals(0, UTF_32_LE_BOM)) {
      source.skip(UTF_32_LE_BOM.size());
      return UTF_32_LE;
    }
    return charset;
  }    

所以,我们需要在二次编码前判断response.body()是否是乱码,如果是,才二次编码,否则就不需要二次处理了。

 

android Retrofit2网络请求封装介绍

android Retrofit2网络请求封装介绍

1. Retrofit使用

Retrofit是一个现在网络请求框架,先来说一下怎么使用

网络权限(添加到AndroidManifest.xml)

<uses-permission android:name="android.permission.INTERNET" />

gradle依赖(添加到build.gradle)

    implementation("com.squareup.okhttp3:okhttp:4.9.2")
    implementation ''com.squareup.retrofit2:retrofit:2.9.0''
    implementation ''com.squareup.retrofit2:converter-gson:2.9.0''
    implementation ''com.squareup.retrofit2:converter-scalars:2.9.0''

定义接口,网络请求的方法

public interface Request {
 
    @GET("/xx/xx")
    Call<ResponseBody> get();
 
}

实例化Retrofit

Retrofit retrofit = new Retrofit.Builder().baseUrl("BASE_URL").build();

通过Retrofit实例创建接口服务对象

Request request = retrofit.create(Request.class);

调用接口中的方法

Call<ResponseBody> call = request.get();

执行异步请求(同步请求需要创建一个新的线程去执行)

call.enqueue(new retrofit2.Callback<ResponseBody>() {
            @Override
            public void onResponse(retrofit2.Call<ResponseBody> call, retrofit2.Response<ResponseBody> response) {
 
            }
 
            @Override
            public void onFailure(retrofit2.Call<ResponseBody> call, Throwable t) {
 
            }
});

2. Retrofit封装

以上可以看出Retrofit是个好东西,可是用起来是比较麻烦的,所有在实际使用中对Retrofit进行一下小小的封装是很有必要的。

定义接口(所有的请求参数都是以map的形式)

public interface Request {
 
    /**
     * 不带参数的get请求
     * @param url
     * @return
     */
    @GET()
    Call<ResponseBody> get(@Url String url);
 
    /**
     * 带参数的get请求
     * @param url
     * @param map 参数默认是map
     * @return
     */
    @GET()
    Call<ResponseBody> get(@Url String url, @QueryMap Map<String,String> map);
 
    /**
     * 不带参数的post请求
     * @param url
     * @return
     */
    @POST()
    Call<ResponseBody> post(@Url String url);
 
    /**
     * 带参数的post请求
     * @param url
     * @param map
     * @return
     */
    @POST()
    @FormUrlEncoded
    Call<ResponseBody> post(@Url String url, @FieldMap Map<String,String> map);
 
    
}

定义RetrofitManager,以单例模式获取Retrofit实例

public enum RetrofitManager {
 
    /**
     * RetrofitManager的实例
     */
    INSTANCE;
 
    /**
     *
     * 后端接口的baseUrl,且只考虑一个url的情况(ip+端口,或者域名)
     */
    private static final String BASE_URL = " Your BASE_URL";
 
    private Retrofit retrofit;
 
    /**
     * 返回Retrofit实例,不添加转换器
     * @return
     */
    public Retrofit getRetrofit(){
        if(retrofit == null){
            retrofit = new Retrofit.Builder()
                    .baseUrl(BASE_URL)
                    .build();
        }
        return retrofit;
    }
}

自定义的RetrofitCallback,在发送请求时,通过匿名对象作为参数获取后端的响应结果。

public abstract class RetrofitCallback {
 
 
    /**
     * 开始执行的方法
     */
    public void onStart(){
        //开启loading
    }
 
    /**
     * 结束执行的方法
     */
    public void onCompleted(){
        //关闭loading
    }
 
    /**
     * 执行成功
     * @param resultJsonString  返回的json字符串
     */
    public abstract void onSuccess(String resultJsonString);
 
    /**
     * 失败
     * @param t 异常
     */
    public abstract void onError(Throwable t);
 
    /**
     * 提示:服务异常
     */
    public void serverErrMsg(){
        //xxx
    }
 
    /**
     * 提示:请求失败
     */
    public void reqErrMsg(){
        //xxx
    }
 
 
    /**
     * 提示:成功
     */
    public void okMsg(){
        //xxx
    }
 
}

定义RetrofitUtil,封装get和post方法。将RetrofitCallback作为请求参数,在发送请求时重写onSuccess和onError方法,执行具体的操作。

public class RetrofitUtil {
 
    private Retrofit(){}
 
    /**
     * 无参的get请求
     * @param url
     * @param callback
     */
    public static void get(String url, RetrofitCallback callback){
        sendRequest(getRequest().get(url),callback);
    }
 
    /**
     * 有参的get请求
     * @param url  请求的url
     * @param map  参数
     * @param callback  请求结束的回调
     */
    public static void get(String url, Map<String,String> map, RetrofitCallback callback){
        sendRequest(getRequest().get(url,map),callback);
    }
 
    /**
     * 无参的post请求
     * @param url
     * @param callback
     */
    public static void post(String url, RetrofitCallback callback){
        sendRequest(getRequest().post(url), callback);
    }
 
    /**
     * 有参的post请求
     * @param url
     * @param map
     * @param callback
     */
    public static void post(String url, Map<String,String> map, RetrofitCallback callback){
        sendRequest(getRequest().post(url,map), callback);
    }
 
 
    /**
     * 获取Request实例
     * @return
     */
    private static Request getRequest(){
        Retrofit retrofit = RetrofitManager.INSTANCE.getRetrofit();
        return retrofit.create(Request.class);
    }
 
    /**
     * 发送请求的共通方法,并对响应结果进行处理
     * @param call
     * @param callback 自定义的Callback
     */
    private void sendRequest(Call<ResponseBody> call,RetrofitCallback callback){
 
        //开启loading
        callback.onStart();
        //异步请求
        call.enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                //关闭loading
                callback.onCompleted();
                if(response.isSuccessful()){
                    //执行RetrofitCallback的onSuccess方法,获取响应结果的json字符串
                    try {
                        String result = response.body().string();
                        callback.onSuccess(result);
                        //响应成功
                        if(StringUtils.equals(result, Constant.SUCCESS)){
                            callback.okMsg();
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }else{
                    //服务异常
                    callback.serverErrMsg();
                }
            }
 
            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {
                callback.onCompleted();
                //请求失败
                callback.onError(t);
 
                callback.reqErrMsg();
               }
            }
        });
    }
}

3. RetrofitUtil使用

get无参请求

RetrofitUtil.get("/xx/xx", new RetrofitCallback() {
    @Override
    public void onSuccess(String resultJsonString) {
                
    }
 
    @Override
    public void onError(Throwable t) {
 
    }
});

get有参请求

Map<String,String> map = new HashMap<>(16);
map.put("key","value");
//xxx
RetrofitUtil.get("/xx/xx", map,new RetrofitCallback() {
    @Override
    public void onSuccess(String resultJsonString) {
        xxxx
    }
 
    @Override
    public void onError(Throwable t) {
        xxxx
    }
});

post请求和get的使用方法相似

最后

本次只对get和post进行了封装,项目中只用到了这些就没有对文件上传下载以及别的请求方式进行封装。且没有添加转换器,可在RetrofitManager的getRetrofit()方法中自行添加。大概的封装思路就是这样的,可以自行发挥。

此文也只是在记录项目中对Retrofit的使用,对Retrofit的原理并没有较深的了解。

到此这篇关于android Retrofit2网络请求封装介绍的文章就介绍到这了,更多相关android Retrofit2网络封装内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!

您可能感兴趣的文章:
  • Android开发Retrofit源码分析
  • SpringBoot中使用HTTP客户端工具Retrofit
  • 微服务间调用Retrofit在Spring Cloud Alibaba中的使用
  • Android使用Retrofit上传文件功能
  • Android Retrofit框架的使用
  • 详解如何魔改Retrofit实例

关于如何进行多个请求并等待数据来自retrofit 2.0中的所有请求 – androidandroid什么意思的介绍已经告一段落,感谢您的耐心阅读,如果想了解更多关于Android OkHttp + Retrofit 取消请求的方法、android retrofit 请求参数格式RequestBody的方法、android retrofit 请求返回String数据中文乱码解决方案、android Retrofit2网络请求封装介绍的相关信息,请在本站寻找。

本文标签: