【问题标题】:Android GAE polymorphism in Client side客户端的Android GAE多态性
【发布时间】:2016-05-13 09:17:07
【问题描述】:

我正在开发一个 Android 应用程序,它使用 Google App Engine (GAE) 作为他的后端,用几句话来说情况就是......

在后端(App Engine Java Endpoints Module)我有一些@Entity 类,例如“Vehicle”、“Car”和“SportCar”,其中“SportCar”是“Car”和“Car”的 @Subclass " 是 "Vehicle" 的 @Subclass。

@Entity
public class Vehicle{
    @Id
    private Long id;
    private String brand;
}

@Subclass(index = true)
public class Car extends Vehicle{

    private int wheelsNumber;
}

@Subclass(index = true)
public class SportCar extends Car{

    private boolean hasTurbo;
}

还有一个端点类“VehicleEndpoint”,其中包含一个返回车辆实体列表的方法。

@Api{name = "vehicleEndpoint", version = "v1", resource = "vehicle", ...}
public class VehicleEndpoint {

@ApiMethod(name = "listVehicles", path = "vehicle", 
           httpMethod = ApiMethod.HttpMethod.GET)
public CollectionResponse<Vehicle> listVehicles(){
     ...
 }
}

所以,当我从客户端(Android 应用程序)调用“listVehicle”时,我收到了 Vehicle 对象的列表,但不知道哪个是“Car”,哪个是“SportCar”。 我无法将这些车辆对象转换为 Car 或 SportCar,因为客户端无法识别子类,因为它们不包含在“VehicleEndpoint”类中。

List<Vehicle> listVehicle = vehicleEndpoint.listVehicles().execute().getItems();

我注意到的另一件事是,在 android 端,我们导入了 Vehicle 类,但它来自另一个包,而不是后端的同一个包(后端包 ->“com.my .example.backend.entity”和客户端导入->“com.my.example.backend.endpoint.vehicleEndpoint.model.Vehicle”)。

我们如何在客户端使用多态性? (总是希望返回最抽象的形式或绝对父级(在本例中为 Vehicle),而不是在客户端检查它是什么类型并使用它)

提前致谢。

【问题讨论】:

    标签: java android google-app-engine objectify


    【解决方案1】:

    我注意到的另一件事是,在 android 端,我们 导入 Vehicle 类,但它来自另一个包,不一样 位于后端的包(后端包-> “com.my.example.backend.entity”和客户端导入-> “com.my.example.backend.endpoint.vehicleEndpoint.model.Vehicle”)。

    这是 Cloud Endpoints 中的正确行为。 “com.my.example.backend.entity”是你的后端项目的包。当您对项目进行 gradle 同步时,Android Studio 会为您创建一个客户端库,它可以方便地将其添加为您的应用项目的一部分。您实际上可以获取 Android Studio 生成的 Cloud Endpoints .jar 并将其复制/粘贴到另一个 Android 项目中并使用您的 API。包名称“com.my.example.backend.endpoint.vehicleEndpoint.model.Vehicle”是 Cloud Endpoints 创建该 jar 文件的方式 - 您可以猜到,它来自端点类中的 API 注释。 "vehicleEndpoint" 例如:

    @Api(
            name = "vehicleEndpoint",
            version = "v1",
            scopes = {
                    Constants.EMAIL_SCOPE},
            clientIds = {
                    Constants.WEB_CLIENT_ID,
                    Constants.ANDROID_CLIENT_ID,
                    Constants.IOS_CLIENT_ID,
                    Constants.API_EXPLORER_CLIENT_ID},
            audiences = {
                    Constants.ANDROID_AUDIENCE},
            namespace = @ApiNamespace(
                    ownerDomain = Constants.API_OWNER,
                    ownerName = Constants.API_OWNER,
                    packagePath = Constants.API_PACKAGE_PATH
            )
    )
    

    这就是它的工作原理,所以是的,包名称会有所不同,因为后者是生成的 jar 文件,我猜这就是它通过 API 注释创建它的方式。

    至于您的投射问题,请记住,当您在客户端中使用 API 方法时,例如:

    List<Vehicle> listVehicle = vehicleEndpoint.listVehicles().execute().getItems();
    

    您将获得一个 Json 响应,然后该响应将返回到您的模型对象中。您知道这一点是因为您可以使用 API 资源管理器来执行您的方法并以纯文本形式查看响应。你在那里看到的一切就是你得到的一切。像铸造这样的事情可能在那里不起作用。您可能需要在 Vehicle 对象中添加一个附加字段来指示它是什么类型。

    希望这能让您深入了解该系统的工作原理。

    【讨论】:

    • 首先感谢您的回复。但是,例如,如果端点类“VehicleEndpoint”中不包含子类“Car”之一,那么我们无法在客户端访问它,因为该子类不会添加到库的包“com. my.example.backend.endpoint.vehicleEndpoint"。
    • 我想在这里添加的另一件事是,我认为这里最好的方法不是直接在前端使用后端的实体类。在前端创建一个单独的实体类并从后端接收 JSON 数据以在前端的这些实体中解析可能会更好吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多