将Retrofit服务声明划分为多个接口

时间:2015-04-23 16:35:25

标签: java android retrofit

我正在创建一个链接到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中的服务声明生成的。每个服务一个接口。”

我一直在阅读有关构图与继承的内容,并且未能掌握如何实现打破宣言的目标。

如何划分界面声明?我缺少最佳做法吗?

谢谢。

3 个答案:

答案 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个人有多个电话时,它可能会更清洁一些。 enter image description here

答案 1 :(得分:4)

只需创建单独的界面。

public interface ProfileService {

  /* ... */
}

public interface AccountService {

  /* ... */
}

ProfileService profileService = mRestAdapter.create(ProfileService.class);
AccountService accountService = mRestAdapter.create(AccountService.class);

答案 2 :(得分:0)

您可以尝试以下操作。

创建2个接口类。

  • ARetrofitApi
  • BRetrofitApi

拨打电话

// 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);