Retrofit 通过泛型将字符串转成bean对象
为了让大家快速理解其中原理,我这里写了一个简单的demo帮助大家理解
private String jsonUser = "{\n" +
" \"age\": 10,\n" +
" \"name\": \"张三\"\n" +
"}";
public void invoke(View view) {
MyRetrofit retrofit = new MyRetrofit();
TestService testService = retrofit.create(TestService.class);
Call<User> call = testService.getUser(jsonUser);
call.enqueue(new Callback<User>() {
@Override
public void onSuccess(User user) {
Toast.makeText(getApplicationContext(), user.toString(), Toast.LENGTH_SHORT).show();
}
});
}
这里模仿了Retrofit的写法调用,区别在于 Call call = testService.getUser(jsonUser); 这里我将 需要转成对象的字符串当做参数传递进去
- 然后是MyRetrofit的代码
public class MyRetrofit {
public <T> T create(Class<T> clazz){
return (T) Proxy.newProxyInstance(clazz.getClassLoader(), new Class<?>[] { clazz },
new InvocationHandler() {
@Override public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
//此处省略adapter的步骤
//通过方法来获取参数的返回值类型 Call<User>
ParameterizedType parameterizedType = (ParameterizedType) method.getGenericReturnType();
//关键步骤,通过返回类型Call<User>,提取User的Type。Retrofit是在ExecutorCallAdapterFactory中的 Utils.getCallResponseType(returnType)方法获取,原理一样
Type returnType = Utils.getParameterUpperBound(0,parameterizedType);
Gson gson = new Gson();
T user = gson.fromJson((String)args[0],returnType);//拦截第一个参数作为目标字符串,用来转换
Call<T> call = new Call<>(user);
return call;
}
});
}
}
代码很简单,通过动态代理的方式创建 TestService 的实现类。没有源码中的Adapter的适配,简单暴力。
- Utils的代码如下
public class Utils {
static Type getParameterUpperBound(int index, ParameterizedType type) {
Type[] types = type.getActualTypeArguments(); //获取参数类型的所有Type类型,这里就不拓展了,想了解的话自行百度
if (index < 0 || index >= types.length) {
throw new IllegalArgumentException(
"Index " + index + " not in range [0," + types.length + ") for " + type);
}
Type paramType = types[index];
if (paramType instanceof WildcardType) {
return ((WildcardType) paramType).getUpperBounds()[0];
}
return paramType;
}
}
核心已经讲完了,剩下贴出其他代码
public class Call<T> {
private T user;
Call(T user){
this.user = user;
}
public void enqueue(Callback<T> callback){
callback.onSuccess(user);
}
}
public interface Callback<T> {
void onSuccess(T user);
}
public interface TestService {
Call<User> getUser(String name);
}
public class User {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
代码比较简单,原理也很简单,希望对大家有点帮助 (第一次正儿八经的写博客,如果有不足的地方望谅解)
源码地址:https://github.com/zhonghaohu/RetrofitConvert