改造通用服务接口

2023-12-26

我正在为 Retrofit 创建一个通用 API 层

这是我的服务类别:

public interface ApiService {

    @POST("api/authenticate")
    Call<Class> postData(@Body Class postBody);

}

public  void  postRequest(String actionUrl,GenericModelClass postBodyModel){
    mApiService.postData(postBodyModel.getClass()).enqueue(new Callback<Class>() {


        @Override
        public void onResponse(Call<Class> call, Response<Class> response) {
            response.getClass().getComponentType();

            Log.d("TFFF", response.toString());
        }

        @Override
        public void onFailure(Call<Class> call, Throwable t) {
          Log.d("TFFF", t.toString());
        }
    });
}

但这给了我:

java.lang.UnsupportedOperationException:尝试序列化 java.lang.Class:a2a.rnd.com.a2ahttplibrary.retrofit.model.User。忘记注册类型适配器?

我想要得到User从通用类型输入,但我收到此异常。


你这样做的方式没有意义,这就是为什么你会得到:

java.lang.UnsupportedOperationException:尝试序列化 java.lang.Class:a2a.rnd.com.a2ahttplibrary.retrofit.model.User。忘记注册类型适配器?

您的服务未指定类型参数。Class把手完全是另一个目的:它是一个对象,代表 JVM 加载的类。序列化和反序列化Class如果有的话,实例的意义也很小,这就是 Gson 不提供它的原因。你想要的只是通用方法。互联网上有无数关于该主题的文章。

接下来,Retrofit 不使用方法类型参数来显着简化底层的类型分析。没关系。

@GET("/")
<T> Call<T> get();

这行不通。那么您将如何传递必要的类型信息数据呢?我能想到的传递该信息的唯一方法是引入一个包装器来保存值及其类型(或类型令牌以简化 Gson)。

final class GenericBody<T> {

    final T body;
    final TypeToken<T> typeToken;

    GenericBody(final T body, final TypeToken<T> typeToken) {
        this.body = body;
        this.typeToken = typeToken;
    }

}

那么示例服务可能声明如下:

interface IGenericService {

    @POST("/")
    Call<Void> post(@Body @SuppressWarnings("rawtypes") GenericBody genericBody);

}

在这里,Call声明不返回任何内容,并且genericBody有意将其设为原始类型,以使其通过 Retrofit 验证。

接下来是Gson部分。

final class GenericBodyTypeAdapterFactory
        implements TypeAdapterFactory {

    private static final TypeAdapterFactory genericBodyTypeAdapterFactory = new GenericBodyTypeAdapterFactory();

    private GenericBodyTypeAdapterFactory() {
    }

    static TypeAdapterFactory getGenericBodyTypeAdapterFactory() {
        return genericBodyTypeAdapterFactory;
    }

    @Override
    public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> typeToken) {
        if ( !GenericBody.class.isAssignableFrom(typeToken.getRawType()) ) {
            return null;
        }
        final TypeAdapter<GenericBody<T>> genericBodyTypeAdapter = new TypeAdapter<GenericBody<T>>() {
            @Override
            public void write(final JsonWriter out, final GenericBody<T> value)
                    throws IOException {
                final T body = value.body;
                final TypeAdapter<T> typeAdapter = gson.getDelegateAdapter(GenericBodyTypeAdapterFactory.this, value.typeToken);
                typeAdapter.write(out, body);
            }

            @Override
            public GenericBody<T> read(final JsonReader in) {
                throw new UnsupportedOperationException();
            }
        };
        @SuppressWarnings("unchecked")
        final TypeAdapter<T> typeAdapter = (TypeAdapter<T>) genericBodyTypeAdapter;
        return typeAdapter;
    }

}

它的作用是:

  • 检查它是否可以处理GenericBody实例;
  • 解决适当的类型适配器<T> by the bound类型标记;
  • 将通用主体值写入输出。

没有执行任何读取操作。

使用示例(充满了模拟(staticResponse(applicationJsonMediaType, "OK"))可以很容易地翻译成你的代码):

private static final TypeToken<List<String>> stringListTypeToken = new TypeToken<List<String>>() {
};

private static final Gson gson = new GsonBuilder()
        .registerTypeAdapterFactory(getGenericBodyTypeAdapterFactory())
        .create();

private static final OkHttpClient client = new OkHttpClient.Builder()
        .addInterceptor(staticResponse(applicationJsonMediaType, "OK"))
        .build();

private static final Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("http://whatever")
        .client(client)
        .addConverterFactory(GsonConverterFactory.create(gson))
        .build();

private static final IGenericService genericService = retrofit.create(IGenericService.class);

public static void main(final String... args)
        throws IOException {
    final GenericBody<List<String>> body = new GenericBody<>(asList("foo", "bar", "baz"), stringListTypeToken);
    genericService.post(body).execute();
}

这会写["foo","bar","baz"]输出流尊重正确配置Gson(反)序列化策略。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

改造通用服务接口 的相关文章

随机推荐

  • 在列表框中处理 WPF 中的图像(内存泄漏)

    我有一个列表框 里面有一堆图像 通过数据模板完成 图像是通过设置项目源创建的
  • 如何在 C# 中声明可选类型? [复制]

    这个问题在这里已经有答案了 Java 8 有Optional
  • 有没有办法在 Kotlin 的数据类中嵌套枚举?

    有没有办法在 Kotlin 的数据类中嵌套枚举 data class D val a Any enum class E F G 或者在函数内声明它内联 fun foo enum class E F G doSomething 我找不到有关允
  • ggplot geom_point 忽略未知的美学:文本问题?

    我正在生成 SVG 分面图 我希望将鼠标悬停在点上时出现工具提示 我正在使用一个textggplot geom point 中的美学来制作工具提示文本 产生警告 Warning Ignoring unknown aesthetics tex
  • ActiveRecord 和 Mogoid::Document :关联

    我有一个基于 ActiveRecord 的模型 另一个基于 Mogoid Document 的模型 可以联合起来吗 例如 2 个型号 class User lt ActiveRecord Base has one avatar depend
  • 如何序列化委托

    让我们看一个网格填充的例子 We have Column班级 它有一个代表设置单元格格式 这需要一些Data并将其转换为string 设置单元格格式委托在设计时是未知的 它可能由插件设置 public class ColumnFormatt
  • Java 中的目录监听器

    我有一个应用程序 我想在其中监听对特定目录所做的任何更改 一旦该目录中添加 删除或更新了任何文件 应用程序应该立即对我进行 ping 操作 从 Java 1 7 开始你可以使用手表服务API http docs oracle com jav
  • 从 Flask 视图返回 JSON 响应

    我有一个函数可以使用 Pandas 分析 CSV 文件并生成包含摘要信息的字典 我想将结果作为 Flask 视图的响应返回 如何返回 JSON 响应 app route summary def summary d make summary
  • 以编程方式从 XSD 创建 XML 文件

    我有一个 XSD 文件 我想在运行时基于 XSD 创建一个 XML 文件 我的问题基本上与this one https stackoverflow com questions 307616 xml instance generation f
  • ASP.NET 自动完成下拉列表

    是否有用于 asp net 自动完成 DropDownList 的控件或 Jquery 插件 如果是 请在此处链接示例 我不想使用asp net ajax控制工具包 我不知道这是否是您要找的内容 但这里有一个类似 Facebook 的不错的
  • 在图像 {graphics} 中添加颜色图例

    在这个例子中 我有一个带有颜色的图像 我想知道我们是否可以添加颜色图例 例如 点与z in 8 10 颜色有红色等 x runif 500 0 5 y runif 500 0 5 z floor runif 500 1 10 xyz dat
  • 未找到 AWS CodeDeploy 命令

    尝试部署 Node js 应用程序时出现错误npm command not found in my post install sh安装后脚本 最奇怪的是我运行的 BeforeInstall 脚本npm install g pm2它工作得很好
  • 在 NTFS 中搜索文件

    我们有一个相当大的磁盘阵列 上面大约有 2 3 百万个 XML 文件 磁盘采用 NTFS 格式 我们想使用通配符搜索文件系统 因此 像 SomePartOfTheFilename 这样的内容将是典型的搜索查询 我们正在使用 Net 并且发现
  • React-选择清除值,同时保留过滤器

    我正在开发一个权限系统 让用户控制谁可以访问 评论 编辑资源 就像您在 Google 云端硬盘上找到的资源一样 我正在使用 React Select multi 让资源所有者选择他想要授予资源访问权限的用户 当我单击反应选择显示的选项时 我
  • Android 中的隐式意图与显式意图(startActivity(intent) 崩溃)

    我是这个世界的新人 我在使用 startActivity intent 时遇到问题 这是清单
  • 按下时更改按钮主题

    我试图在按下按钮时更改按钮的数据主题 我在按钮的 onClick 处理程序中调用此 JavaScript 函数 function changeNextButtonColor var nextButton document getElemen
  • 在另一个类中使用 JSONArray?

    我有一个微调器 可以在下拉列表中加载客户的姓名 微调器从 JSON 数组获取字符串 我还有一些文本视图 当旋转器选择更改时 应加载所选客户的姓名 地址 电话号码 但是 JSONArray 在另一个类中使用 我如何在另一个类中使用 JSONA
  • 在 Visual Studio 2015 中显示单元测试的描述属性

    有谁知道如何在 Visual Studio 2015 测试运行期间显示描述属性 例如给出这个测试 TestMethod TestCategory With Fakes Description Posting a blog entry wit
  • TIME-WAIT刺杀和SO_REUSEADDR有什么区别

    我正在阅读有关使用 SO LINGER 套接字选项通过将逗留时间设置为零来有意 暗杀 时间等待状态的内容 该书的作者接着说我们永远不应该这样做 并且一般来说我们永远不应该干扰时间等待状态 然后他立即建议使用 SO REUSEADDR 选项来
  • 改造通用服务接口

    我正在为 Retrofit 创建一个通用 API 层 这是我的服务类别 public interface ApiService POST api authenticate Call