我正在创建一个链接到API的应用程序,其中包含大约265种方法。我非常希望将这些API的声明分解为多个文件,以保持它们的有序性和可访问性。但是,Retrofit明确禁止通过扩展组合接口。
java.lang.IllegalArgumentException: Interface definitions must not extend other interfaces.
我一直试图将其声明如下。
public interface ApiService extends ProfileService, AccountService {
// Empty interface, methods divided into other services
}
public interface ProfileService {
@GET("/api/v1/protected/profile")
public void getProfile(Callback<Profile> callback);
...
}
public interface AccountService {
@GET("/api/v1/protected/account")
public void getAccount(Callback<Account> callback);
...
}
在拉取请求中有关于此问题的讨论。图书馆作者已经决定扩展这样的接口不符合图书馆的精神。 https://github.com/square/retrofit/pull/676
杰克沃顿(作者)说“改造有利于作曲”。并且回应“你真的有一个带有大量代理的单个适配器吗?”,“是的。它们是从protos中的服务声明生成的。每个服务一个接口。”我一直在阅读有关构图与继承的内容,并且未能掌握如何实现打破宣言的目标。
如何划分界面声明?我缺少最佳做法吗?
谢谢。
答案 0 :(得分:5)
我还在试验这是否是使用它的最好方法,但这是我到目前为止所做的。它可能不是最干净的方法,但我喜欢它与一个100 api呼叫的服务。将它拆分一点,使其更容易阅读。
这是访问数据的主要类。我已经看到很多将我所拥有的两个静态方法分离到一个单独的类中,但我只是将它作为一个包含在内。
public class RetrofitApi {
public enum ApiTypes {
USER_API(UserApi.class);
private final Class<? extends RetrofitApi> apiClass;
ApiTypes(Class<? extends RetrofitApi> apiClass){
this.apiClass = apiClass;
}
Class<? extends RetrofitApi> getApiType() {return this.apiClass;}
}
public static <T> T getApi(RetrofitApi.ApiTypes type) {
try {
return (T) type.getApiType().newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
public static RestAdapter getRestAdapter() {
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint(BASE_URL)
.setLogLevel(retrofit.RestAdapter.LogLevel.HEADERS)
.build();
return restAdapter;
}
}
每项服务都有自己的API。这确实意味着更多的课程。我将它们分成api,服务,模型。 API是您将使用和公开的高级别。服务或多或少只是一个呼叫列表。而Model是模型(数据对象)。
public class UserApi extends RetrofitApi {
private UserService service;
public UserApi() {
RestAdapter restAdapter =
RetrofitApi.getRestAdapter();
service = restAdapter.create(UserService.class);
}
public void login(String email,
String password,
Callback<User> callback) {
service.login(email, password, callback);
}
}
服务是界面。它或多或少只是一个暴露的api调用列表。
public interface UserService {
@GET("/api/users/login")
void login(@Query("email") String email,
@Query("password") String password,
Callback<User> callback);
}
然后使用它。
UserApi api = RetrofitApi.getApi(RetrofitApi.ApiTypes.USER_API);
api.login(email,password,callback);
这是项目结构。对我来说,此刻看起来很干净。我相信当我有20多个时,它最终会变大。但是当这20个人有多个电话时,它可能会更清洁一些。
答案 1 :(得分:4)
只需创建单独的界面。
public interface ProfileService {
/* ... */
}
public interface AccountService {
/* ... */
}
ProfileService profileService = mRestAdapter.create(ProfileService.class);
AccountService accountService = mRestAdapter.create(AccountService.class);
答案 2 :(得分:0)
您可以尝试以下操作。
创建2个接口类。
拨打电话
// ARetrofitApi
@FormUrlEncoded
@POST("get_favorite_food/{id}")
Call<JsonObject> getFavoriteFood(@Path("id") String userId,
@Field("image") String image,
@Field("name") String foodName);
// BRetrofitApi
@FormUrlEncoded
@POST("get_favorite_sport/{id}")
Call<JsonObject> getFavoriteSport(@Path("id") String userId,
@Field("image") String image,
@Field("name") String sportName);
在您的构建器中
private static final String BASE_URL = "http://192.168.1.4/myapp/";
private static RetrofitClient mInstance;
private Retrofit retrofit;
private RetrofitClient() {
retrofit = new Retrofit.Builder().baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
public static synchronized RetrofitClient getInstance() {
if (mInstance == null) {
mInstance = new RetrofitClient();
}
return mInstance;
}
public ARetrofitApi aGetApi() {
return retrofit.create(ARetrofitApi.class);
}
public BRetrofitApi bGetApi() {
return retrofit.create(BRetrofitApi.class);
}
拨打电话
// Use RetroFit To Feed To MySQL
Call<JsonObject> call = RetrofitClient.getInstance()
.aGetApi()
.getFavoriteFood(userId,
image,
foodName);
// Use RetroFit To Feed To MySQL
Call<JsonObject> call = RetrofitClient.getInstance()
.bGetApi()
.getFavoriteSport(userId,
image,
sportName);