【问题标题】:POST from Android to Ruby on Rails WebAPI with retrofit2从 Android POST 到 Ruby on Rails WebAPI 与改造2
【发布时间】:2017-01-23 23:28:15
【问题描述】:

我有一个通过 Ruby on Rails 构建的有效 WebApi。我在此 WebAPI 中有条目,我可以通过 @GET 请求成功列出和访问,但我无法从 Android 向 WebAPI 发布新条目。

此外,我可以从一个名为 POSTMAN 的应用程序向 WebAPI 发布一个条目,当我尝试调用我的 WebApi 接口中定义的 createCourse 方法时,我的 WebApi 日志显示没有进行调用的证据。

请求显然一开始就无法发送的事实让我感到困惑,但无论哪种情况,我都认为问题在于我如何调用我的改造 POST。我知道this 发帖人也有类似的问题,但他的项目结构与我的不同,我不确定它是如何应用的。

在我的 WebApi 界面中,这里是工作的 @GET 和功能失调的 @POST

//CREATE
    @Headers("Content-type: application/json")
    @POST("/courses/create/")
    Call<Course> createCourse(@Body Course CourseName);
//LIST
@GET("/courses")
    Call<List<Course>> getCourses();

同样在我的WebApi界面中,我有以下

public static class Course {

    public void setName(String name) {
        this.name = name;
    }

    public void setLocation(String location) {
        this.location = location;
    }

    public void setStartDate(String startDate) {
        this.startDate = startDate;
    }

    public void setEndDate(String endDate) {
        this.endDate = endDate;
    }

    @SerializedName("name") private String name;
    @SerializedName("location") private String location;
    @SerializedName("startDate") private String startDate;
    @SerializedName("endDate") private String endDate;

    public String getName() {
        return name;
    }

    public String getLocation() {
        return location;
    }

    public String getStartDate() {
        return startDate;
    }

    public String getEndDate() {
        return endDate;
    }
}

我有一个扩展应用程序的 App 类,在不相关的东西中,它包含以下内容

public WebApi getWebApi() {
    if (webApi == null) {
        webApi = new Retrofit.Builder()
                .addConverterFactory(GsonConverterFactory.create())
                .baseUrl("https://validurl.com") //i plug in something valid in implementation
                .build()
                .create(WebApi.class);
    }
    return webApi;
}

在我调用@GET 请求的活动中,它看起来像这样

Observable.just(getApi().getCourses())
            .subscribeOn(Schedulers.io())
            .map(x -> {
                try {
                    return x.execute();

                } catch (IOException ex) {
                    throw new RuntimeException(ex);
                }
            })
            .map(x -> x.body())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(x -> {
                adapter.updateCourses(x);
            }, ex -> {
            });

在我调用@GET 的活动中,我已经定义了

public WebApi getApi() {
    return ((App) getApplication()).getWebApi();
}

“适配器”位与我的问题无关,因为它与我的本地数据库有关 - 它工作正常!

我称之为(非工作)@POST,它看起来像这样

    WebApi.Course onlinecourse = new WebApi.Course();
    onlinecourse.setName(localcourse.name());
    onlinecourse.setLocation(localcourse.location());
    onlinecourse.setStartDate(localcourse.start_date());
    onlinecourse.setEndDate(localcourse.end_date());

之后,我使用以下方法之一(均无效)尝试发送 POST(公平地说,我应该在这里使用我在其他地方定义的 getWebApi() 方法,而不是使用应用程序的原生方法转换后的类,但结果是一样的)

((App) getApplication()).getWebApi().createCourse(onlinecourse);

    Observable.just(((App) getApplication()).getWebApi().createCourse(onlinecourse))
            .subscribeOn(Schedulers.io())
            .map(x -> {
                try {
                    return x.execute();

                } catch (IOException ex) {
                    throw new RuntimeException(ex);
                }
            })
            .map(x -> x.body())
            .observeOn(AndroidSchedulers.mainThread())
            ;

我想这个电话是不工作的地方。也许我不了解改造是如何工作的,但我认为我拥有它的方式将对象作为 JSON 发送。我不确定这是否属实,我如何检查,或者为什么似乎没有 POST 请求首先发送到我的 API(它不像 GET 那样出现在日志中)

【问题讨论】:

  • 您的应用程序崩溃了吗?调用是否引发异常?我没有看到 Retrofit.Builder().addCallAdapterFactory(RxJavaCallAdapterFactory.create())
  • 我会尝试添加 addCallAdapterFactory 行。照原样,应用程序既不会崩溃也不会抛出任何可见的异常......它的行为就像从未进行过调用或调用有效但它永远不会到达我的 WebApi。
  • 我已经导入了 retrofit2.Retrofit 和 retrofit2.converter.gson.GsonConverterFactory 并尝试了 retrofit2.* 但 RxJavaCallAdapterFactory 无法识别
  • 尝试将其放入您的应用程序 gradle 文件中:编译 'com.squareup.retrofit2:adapter-rxjava:2.1.0'。您也可以尝试:'com.squareup.okhttp3:logging-interceptor:3.3.1' 来查看 Retrofit 中发生了什么(阅读文档以了解如何使用后者)
  • 今晚我可以在大约 3 小时内恢复时试试这个。谢谢。

标签: java android rx-java retrofit2


【解决方案1】:

你永远不会订阅你的 Observable,所以它永远不会被评估。此外,如果您打算使用 RxJava,那么您创建 WebApi 接口的方式也是错误的。

首先,将您的 WebApi 接口更改为:

//CREATE 
    @Headers("Content-type: application/json") 
    @POST("/courses/create/") 
    Observable<Course> createCourse(@Body Course CourseName);
//LIST 
@GET("/courses") 
    Observable<List<Course>> getCourses();

所以现在,当您调用 getCourses 时,您将获得一个 Observable。

其次,像这样调用你的方法:

  (App) getApplication()).getWebApi()
              .createCourse(onlinecourse))
              .subscribeOn(Schedulers.io())          
              .observeOn(AndroidSchedulers.mainThread()) 
              .subscribe(new Observer<Course>() {
                @Override
                public void onCompleted() {
                    //Code here
                }

            @Override
            public void onError(Throwable e) {
                    //Code here
            }

            @Override
            public void onNext(Course course) {
                    //Code here - Do something with course!

            }

这将是你的工作。 编码愉快!

【讨论】:

  • 我不知道解释为什么,但这不起作用。将 Call 转换为 Observable 后,我尝试在 .map(x -&gt; x.body()) 中使用的“x”就像 Course 类的对象而不是 retrofit2 响应,所以我不能调用像“body()”这样的 retrofit2 方法。有什么想法吗?
  • 你不需要调用 ResponseBody.body(),或者调用“body()”。您的 Retrofit 已经使用 Gson 为您解析了 Json 对象。当 Retrofit 将它返回给您时,它会为您提供一个 Course 对象。这就是你需要的吧??您所要做的就是在 onNext(Course course) 方法中处理这个对象。我不认为你需要地图功能......所以我把它从我的答案中删除了
  • 你说得对。我只是不知道应该做哪些改变,因为我最初并没有计划使用 RxJavaCallAdapterFactory。非常感谢。对于将来想要参考此内容的任何人,请知道在此答案中 RespostaInsereImagem 将替换为 WebApi.Course 。干杯!
  • 不客气!对此感到抱歉...这是代码的复制/粘贴。现在已经修复了!
猜你喜欢
  • 2017-01-16
  • 2013-11-16
  • 2012-10-02
  • 1970-01-01
  • 2013-02-01
  • 2012-01-14
  • 2011-01-08
  • 2011-01-21
  • 2011-11-01
相关资源
最近更新 更多