【问题标题】:Sending data from Room persistence library using Retrofit使用 Retrofit 从 Room 持久性库发送数据
【发布时间】:2019-02-12 08:07:18
【问题描述】:

我最近接手了一个使用 Android 的 Room 持久性库以及 Retrofit 的项目。不幸的是,我对这两个库都不是很了解。

我目前正在尝试将使用 Room 保存的 JSON 记录数组发送到使用改造的 API。

我的实体如下所示:

@Entity(tableName = "location_table")
public class LocationEntity implements Serializable {

    @NonNull
    @PrimaryKey(autoGenerate = true)
    private int id;

    @SerializedName("job_id")
    @ColumnInfo(name = "job_id")
    @Expose
    private String job_id;

    @SerializedName("coordinates")
    @ColumnInfo(name = "coordinates")
    @Expose
    private String coordinates;

    @SerializedName("created_at")
    @ColumnInfo(name = "created_at")
    @Expose
    private String created_at;

    public int getId() { return id; }
    public void setId(int id) { this.id = id; }

    public String getJob_id() { return job_id; }
    public void setJob_id(String job_id) { this.job_id = job_id; }

    public String getCoordinates() { return coordinates; }
    public void setCoordinates(String coordinates) { this.coordinates = coordinates; }

    public String getCreated_at() { return created_at; }
    public void setCreated_at(String created_at) { this.created_at = created_at; }

    @Ignore
    public LocationEntity() {
        // DATA TO IGNORE
    }

    public LocationEntity(String job_id, String coordinates, String created_at) {
        this.job_id = job_id;
        this.coordinates = coordinates;
        this.created_at = created_at;
    }
}

在我的 DOA 中,我有:

@Dao
public interface LocationDAO {
    @Query("SELECT * from location_table ORDER BY id ASC")
    List<LocationEntity> getAll();
}

并且存储库有:

public class LocationRepository {

    private static BudtrackDatabase budtrackDatabase;
    public LocationRepository(Context context) {
        budtrackDatabase = Room.databaseBuilder(context, BudtrackDatabase.class, AppConstants.DATABASE_NAME).build();
    }

    public static List<LocationEntity> getLocations() {
        return budtrackDatabase.locationDAO().getAll();
    }
}

我的要求:

public interface LocationRequest {

    /**
     * Send through multiple locations
     * @param token
     * @param coordinates
     */
    @FormUrlEncoded
    @POST("api/coordinates")
    Call<String> sendLocations(@Field("token") String token,
                               @Field("coordinates[]") List<LocationEntity> coordinates);
}

然后我尝试使用改造发送数据,如下所示:

String token = "12345";
List<LocationEntity> locations = locationRepository.getLocations();

Call<String> callLocation = sendLocationService.sendLocations(token, locations);
callLocation.enqueue(new Callback<String>() {
    @Override
    public void onResponse(Call<String> call, Response<String> response) {
        if (response.isSuccessful()) {
            // Logic for success
        } else {
            try {
                JSONObject jObjError = new JSONObject(response.errorBody().string());
                Toast.makeText(activity, jObjError.getString("message"), Toast.LENGTH_LONG).show();
            } catch (Exception e) {
                Toast.makeText(activity, e.getMessage(), Toast.LENGTH_LONG).show();
            }
        }
    }

    @Override
    public void onFailure(Call<String> call, Throwable t) {
        Log.e("Failed To Send Location", t.getMessage());
    }
});

然后我像这样在 API 端获取数据:

"coordinates" : [ 
        "com.yard8.budtrack.data.location.LocationEntity@4d87c17", 
        "com.yard8.budtrack.data.location.LocationEntity@6c60804", 
        "com.yard8.budtrack.data.location.LocationEntity@fdad1ed", 
        "com.yard8.budtrack.data.location.LocationEntity@66fc822", 
        "com.yard8.budtrack.data.location.LocationEntity@8dec2b3", 
        "com.yard8.budtrack.data.location.LocationEntity@f9da070", 
];

发送数据以使其作为 JSON 数组通过的正确方法是什么?

【问题讨论】:

  • 你遇到了什么问题?
  • 我在 API 上收到的数据似乎只是一个字符串,例如“com.yard8.budtrack.data.location.LocationEntity@4d87c17”,而不是具有坐标等属性的实际对象和 created_at
  • 您是否尝试过在 sendLocations() 函数中使用 ArrayList 而不是“List”?
  • 在从 LocationDAO 编译时尝试使用 ArrayList 会引发错误,提示“错误:不确定如何将游标转换为此方法的返回类型”
  • 你试过 ArrayList 吗?

标签: android retrofit2 android-room


【解决方案1】:

我可能一直试图让事情变得过于复杂,而我需要做的就是改变

@Field("coordinates[]") List<LocationEntity> coordinates

@Field("coordinates") String coordinates

然后在调用之前使用...

Gson gson = new Gson();
String locations = gson.toJson(locationRepository.getLocations());

...并将它作为我的第二个参数传递。

Call<String> callLocation = sendLocationService.sendLocations(token, locations);

我真的认为这仅适用于单个对象而不是它们的列表,因为我一直在接收数据服务器端。

【讨论】:

    【解决方案2】:

    你有没有尝试过这样的事情

    1.创建新类

    class ParentEntity{
    
            private List<LocationEntity> locationEntities;
    
            public List<LocationEntity> getLocationEntities() {
                return locationEntities;
            }
    
            public void setLocationEntities(List<LocationEntity> locationEntities) {
                this.locationEntities = locationEntities;
            }
        }
    

    2。然后在您的响应改造中

    // ....... //
    @Override
    public void onResponse(Call<String> call, Response<String> response) {
        if (response.isSuccessful()) {
            // Logic for success
            ParentEntity readObj = response.body();
            List<LocationEntity> locations = readObj.getLocationEntities();
    
            // DO SOMETHING YOU WANT
    
        } else {
            try {
                JSONObject jObjError = new JSONObject(response.errorBody().string());
                Toast.makeText(activity, jObjError.getString("message"), Toast.LENGTH_LONG).show();
            } catch (Exception e) {
                Toast.makeText(activity, e.getMessage(), Toast.LENGTH_LONG).show();
            }
        }
    }
    // ....... //
    

    更新 尝试使用@Body,可能结构如下 1.新建类

    class ParentEntity{
    
            private LocationEntity location;
            private String token;
    
            public LocationEntity getLocation() {
                return location;
            }
    
            public void setLocation(LocationEntity location) {
                this.location = location;
            }
    
            public String getToken() {
                return token;
            }
    
            public void setToken(String token) {
                this.token = token;
            }
        }
    
    1. 使用正文而不是字段,也没有@FormUrlEncoded

      @POST("/") 调用 sendLocations(@Body ParentEntity parentEntity);

    【讨论】:

    • 我的错,也许我没有正确解释我的问题。我遇到的问题是我需要访问我发布数据的 API 端的位置实体。它是一个 PHP 后端,所以我想以 JSON 格式将我的位置实体数组发送到 API 端点,但它似乎并没有按照我的预期发送它。
    • 您的服务器端是否收到了来自此 POST 操作的值?你能查到吗?
    • 抱歉,我没注意到,这是服务器端,请参见:“坐标”:[“com.yard8.budtrack.data.location.LocationEntity@4d87c17”,
    • 我的问题底部显示坐标数组的 sn-p 是我在服务器端接收的数据。它似乎是一个字符串数组,告诉我它们是 LocationEntities,但我实际上并没有将它作为对象接收。
    • 哈哈是的,没关系。我假设我打算在发送对象时将其转换为 JSON,但我认为我在某处读到了 Android Room 或 Retrofit 会自动执行此操作的内容?
    猜你喜欢
    • 2019-04-25
    • 2018-11-11
    • 1970-01-01
    • 2019-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多