【问题标题】:Interface in Room and Retrofit房间接口和改造
【发布时间】:2021-07-18 21:18:03
【问题描述】:

当使用 retrofit 库时,您创建了一个 interface,其中包含所有端点的函数,但您从未在任何地方实现它。我的问题是这个接口在哪里实现?在使用 android Room

创建 DAO 时,我注意到了相同的模式

【问题讨论】:

标签: android retrofit2 android-room


【解决方案1】:

他们使用两种不同的方法,Retrofit 利用 Java 反射 proxy 这是一个在运行时实现接口的工具,您的代理的 invoke 方法将通过反射检索被调用的方法方案,并可以基于它工作。事实上,改造只能使用方法元数据。

代理是一种从接口创建对象而不使用代码实现它们的方法,而是通过一个简单的调用方法来获取这些参数

@Override
    public Object invoke(Object proxy, Method method, Object[] args) 
      throws Throwable {
        Log.d("proxyCall", method.getName());

        return Response (...);
    }

您也可以从方法中获取其他信息(例如注释,例如 @GET 等)

另一方面,Room 在编译期间使用annotation processors 生成代码(您可以使用annotationProcessorkapt 在gradle 配置中添加它的处理器,也就是编译器)。 您可以在模块的 build 文件夹中找到 Room 生成的源代码。

【讨论】:

  • 这是一个很好的细分。谢谢。
【解决方案2】:

Retrofit 使用 Java 动态代理方法在运行时创建类,这需要一个接口,因此您只需要定义您的接口,并且 Retrofit 将在运行时为您的接口构建一个类型安全的实现。

【讨论】:

    【解决方案3】:

    房间数据库同时使用注释处理器和反射。它使用注解处理器为注解为@DAO@Database的类生成Java代码,并生成带有_Impl后缀的实现类。

    它使用反射来查找数据库实现类。当你调用Room.databaseBuilder(context, AppDatabase.class, databaseName).build();它会这样调用,后缀的值为_Impl

      @NonNull
        static <T, C> T getGeneratedImplementation(Class<C> klass, String suffix) {
            final String fullPackage = klass.getPackage().getName();
            String name = klass.getCanonicalName();
            final String postPackageName = fullPackage.isEmpty()
                    ? name
                    : (name.substring(fullPackage.length() + 1));
            final String implName = postPackageName.replace('.', '_') + suffix;
            //noinspection TryWithIdenticalCatches
            try {
    
                @SuppressWarnings("unchecked")
                final Class<T> aClass = (Class<T>) Class.forName(
                        fullPackage.isEmpty() ? implName : fullPackage + "." + implName);
                return aClass.newInstance();
            } catch (ClassNotFoundException e) {
                throw new RuntimeException("cannot find implementation for "
                        + klass.getCanonicalName() + ". " + implName + " does not exist");
            } catch (IllegalAccessException e) {
                throw new RuntimeException("Cannot access the constructor"
                        + klass.getCanonicalName());
            } catch (InstantiationException e) {
                throw new RuntimeException("Failed to create an instance of "
                        + klass.getCanonicalName());
            }
        }
    

    房间限制了反射的使用,所以房间的速度受反射影响不大

    【讨论】:

      猜你喜欢
      • 2021-01-03
      • 1970-01-01
      • 1970-01-01
      • 2020-04-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多