Retrofit自定义Converter之StringConverterFactory

之前写过一篇 浅谈Retrofit封装-让框架更加简洁易用 里面采用的是GsonConverterFactory,对于retrofit的返回类型要求只能是: 具体对象、jsonObject、jsonArray这三种。由于服务器返回的基础数据格式不固定,所以封装请求类的时候每个请求方式都要封装两个方法,而retrofit又必须添加一种解析器,本人对代码有洁癖,抽时间写了个StringConverterFactory将数据解析成最基本的String返回。
参考GsonConverterFactory源码,自定义解析器还是比较好写的,一共三个类,直接贴了

解析器 工厂

package com.sunshine.retrofit.converter;

import java.lang.annotation.Annotation;
import java.lang.reflect.Type;

import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import retrofit2.Converter;
import retrofit2.Retrofit;

/**
 * Created by 耿 on 2016/9/6.
 */
public class StringConverterFactory extends Converter.Factory {

    public static StringConverterFactory create() {
        return new StringConverterFactory();
    }

    private StringConverterFactory() {

    }

    @Override
    public Converter responseBodyConverter(Type type, Annotation[] annotations,
                                                            Retrofit retrofit) {
        return new StringResponseBodyConverter();
    }

    @Override
    public Converter requestBodyConverter(Type type,
                                                          Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
        return new StringRequestBodyConverter();
    }
}

Response响应体类

package com.sunshine.retrofit.converter;

import java.io.IOException;

import okhttp3.ResponseBody;
import retrofit2.Converter;

/**
 * Created by 耿 on 2016/9/6.
 */
public class StringResponseBodyConverter implements Converter<ResponseBody, String> {
    @Override
    public String convert(ResponseBody value) throws IOException {
        try {
            return value.string();
        } finally {
            value.close();
        }
    }
}

Request 请求体类

package com.sunshine.retrofit.converter;

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.nio.charset.Charset;

import okhttp3.MediaType;
import okhttp3.RequestBody;
import okio.Buffer;
import retrofit2.Converter;

/**
 * Created by 耿 on 2016/9/6.
 */
public class StringRequestBodyConverter  implements Converter<String, RequestBody> {
    private static final MediaType MEDIA_TYPE = MediaType.parse("application/json; charset=UTF-8");
    private static final Charset UTF_8 = Charset.forName("UTF-8");

    StringRequestBodyConverter() {
    }

    @Override public RequestBody convert(String value) throws IOException {
        Buffer buffer = new Buffer();
        Writer writer = new OutputStreamWriter(buffer.outputStream(), UTF_8);
        writer.write(value);
        writer.close();
        return RequestBody.create(MEDIA_TYPE, buffer.readByteString());
    }
}

在构建retrofit时替换掉原来的GsonConverterFactory就可以了

 Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl(BASE_URL + "/")
                    .addConverterFactory(StringConverterFactory.create())
                    .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                    .client(OkhttpProvidede.okHttpClient(mAppliactionContext, BASE_URL, SERVERS))
                    .build();

这里要注意,retrofit对于解析器是由添加的顺序分别试用的,解析成功就直接返回,失败则调用下一个解析器。如果你们的服务器一开始基本返回格式不固定,而后来在你的建议或者坚持下,大发善心的把后面新需求的API的返回格式都固定了的话,可以按如下代码的方式将GsonConverterFactory添加在StringConverterFactory前面。这样如果是固定格式的就可以直接解析返回了。

Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl(BASE_URL + "/")
                     .addConverterFactory(GsonConverterFactory.create())
                    .addConverterFactory(StringConverterFactory.create())
                    .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                    .client(OkhttpProvidede.okHttpClient(mAppliactionContext, BASE_URL, SERVERS))
                    .build();

然后以后调用请求就可以直接

 new HttpUtil.Builder("favorite_authorized/list?page=1")
                    .Version()
                    .CacheTime("3600*24")
                    .Params("carId", sb.toString())
                    .Params(sortMap_)
                    .Success((s) -> {
                        ld_.dismiss();
                        BaseModel model = new BaseModel(s);
                    })
                    .Error((v) -> {
                        ld_.dismiss();
                        handler_.obtainMessage(MSG, v[1]).sendToTarget();
                    })
                    .get();
        });

再也不用去管返回格式是jsonObject还是jsonArray了。

我建了一个QQ群(群号:121606151),用于大家讨论交流Android技术问题,有兴趣的可以加下,大家一起进步。

你可能感兴趣的:(android)