【发布时间】:2021-07-18 21:18:03
【问题描述】:
当使用 retrofit 库时,您创建了一个 interface,其中包含所有端点的函数,但您从未在任何地方实现它。我的问题是这个接口在哪里实现?在使用 android Room
创建 DAO 时,我注意到了相同的模式【问题讨论】:
标签: android retrofit2 android-room
当使用 retrofit 库时,您创建了一个 interface,其中包含所有端点的函数,但您从未在任何地方实现它。我的问题是这个接口在哪里实现?在使用 android Room
创建 DAO 时,我注意到了相同的模式【问题讨论】:
标签: android retrofit2 android-room
他们使用两种不同的方法,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 生成代码(您可以使用annotationProcessor 或kapt 在gradle 配置中添加它的处理器,也就是编译器)。
您可以在模块的 build 文件夹中找到 Room 生成的源代码。
【讨论】:
Retrofit 使用 Java 动态代理方法在运行时创建类,这需要一个接口,因此您只需要定义您的接口,并且 Retrofit 将在运行时为您的接口构建一个类型安全的实现。
【讨论】:
房间数据库同时使用注释处理器和反射。它使用注解处理器为注解为@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());
}
}
房间限制了反射的使用,所以房间的速度受反射影响不大
【讨论】: