【问题标题】:Http request with Retrofit and RxJava使用 Retrofit 和 RxJava 的 Http 请求
【发布时间】:2016-07-20 08:42:02
【问题描述】:

我正在请求一个带有 Retrofit 2 库的 Web 服务 API。我有以下 API 的 URL 代码:

String ENDPOINT = "https://api.trakt.tv/";

@GET("movies/popular?limit=10&extended=full,images")
public Observable<PopularMoviesResponse> getPopularMovies(@Header("trakt-api-version") String trakt_api_version,
                                                  @Header("trakt-api-key") String trakt_api_key,
                                                  @Query("page") String page);

我在:

public Observable<List<PopularMovies>> fetchPopularMovies(String trakt_api_version,
                                                          String trakt_api_key,
                                                          String page) {
    return movieService
            .getPopularMovies(trakt_api_version, trakt_api_key, page)
            .concatMap(new Func1<PopularMoviesResponse, Observable<? extends List<PopularMovies>>>() {
                @Override
                public Observable<? extends List<PopularMovies>> call(final PopularMoviesResponse popularMoviesResponse) {
                    Log.d("uuuuuu", "oooooo");
                    return Observable.create(new Observable.OnSubscribe<List<PopularMovies>>() {
                        @Override
                        public void call(Subscriber<? super List<PopularMovies>> subscriber) {
                            Log.d("uuuuuu", "oooooo");
                            try {
                                if (subscriber.isUnsubscribed()) return;
                                subscriber.onNext(popularMoviesResponse.getPopularMovies());
                                subscriber.onCompleted();
                            } catch (Exception e) {
                                subscriber.onError(e);
                            }
                        }
                    });

                }
            });
}

日志数据告诉http状态码是200,okhttp正常记录响应。但是,在第二个 sn-p 代码中,没有到达日志!有什么问题?

更新,

这是订阅 observable 的代码:

public void getPopularMovies(final String page) {
    mDataManager.fetchPopularMovies(TraktAPI.TRAKT_API_VERSION.getValue(), TraktAPI.TRAKT_API_KEY.getValue(), page)
            .observeOn(AndroidSchedulers.mainThread())
            .subscribeOn(Schedulers.io())
            .subscribe(new Observer<List<PopularMovies>>() {
                @Override
                public void onCompleted() {
                }

                @Override
                public void onError(Throwable e) {
                    mMvpView.showEmpty();
                }

                @Override
                public void onNext(List<PopularMovies> popularMoviesList) {
                    Log.d("onNext", "pppppppppppp");
                    mMvpView.showListOfPopularMovies(popularMoviesList);
                }
            });
}

我在订阅代码中记录了 onError,我得到了以下堆栈跟踪:

07-20 12:15:16.547 2056-2056/org.unrwa.edits W/System.err: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2 path $
07-20 12:15:16.548 2056-2056/org.unrwa.edits W/System.err:     at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:221)
07-20 12:15:16.549 2056-2056/org.unrwa.edits W/System.err:     at com.google.gson.TypeAdapter.fromJson(TypeAdapter.java:260)
07-20 12:15:16.549 2056-2056/org.unrwa.edits W/System.err:     at retrofit2.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:33)
07-20 12:15:16.549 2056-2056/org.unrwa.edits W/System.err:     at retrofit2.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:23)
07-20 12:15:16.550 2056-2056/org.unrwa.edits W/System.err:     at retrofit2.OkHttpCall.parseResponse(OkHttpCall.java:154)
07-20 12:15:16.550 2056-2056/org.unrwa.edits W/System.err:     at retrofit2.OkHttpCall.execute(OkHttpCall.java:118)
07-20 12:15:16.550 2056-2056/org.unrwa.edits W/System.err:     at retrofit2.RxJavaCallAdapterFactory$CallOnSubscribe.call(RxJavaCallAdapterFactory.java:107)
07-20 12:15:16.551 2056-2056/org.unrwa.edits W/System.err:     at retrofit2.RxJavaCallAdapterFactory$CallOnSubscribe.call(RxJavaCallAdapterFactory.java:88)
07-20 12:15:16.551 2056-2056/org.unrwa.edits W/System.err:     at rx.Observable$2.call(Observable.java:162)
07-20 12:15:16.552 2056-2056/org.unrwa.edits W/System.err:     at rx.Observable$2.call(Observable.java:154)
07-20 12:15:16.552 2056-2056/org.unrwa.edits W/System.err:     at rx.Observable$2.call(Observable.java:162)
07-20 12:15:16.552 2056-2056/org.unrwa.edits W/System.err:     at rx.Observable$2.call(Observable.java:154)
07-20 12:15:16.553 2056-2056/org.unrwa.edits W/System.err:     at rx.Observable$2.call(Observable.java:162)
07-20 12:15:16.553 2056-2056/org.unrwa.edits W/System.err:     at rx.Observable$2.call(Observable.java:154)
07-20 12:15:16.553 2056-2056/org.unrwa.edits W/System.err:     at rx.Observable$2.call(Observable.java:162)
07-20 12:15:16.554 2056-2056/org.unrwa.edits W/System.err:     at rx.Observable$2.call(Observable.java:154)
07-20 12:15:16.555 2056-2056/org.unrwa.edits W/System.err:     at rx.Observable$2.call(Observable.java:162)
07-20 12:15:16.555 2056-2056/org.unrwa.edits W/System.err:     at rx.Observable$2.call(Observable.java:154)
07-20 12:15:16.556 2056-2056/org.unrwa.edits W/System.err:     at rx.Observable.unsafeSubscribe(Observable.java:8098)
07-20 12:15:16.556 2056-2056/org.unrwa.edits W/System.err:     at rx.internal.operators.OperatorSubscribeOn$1$1.call(OperatorSubscribeOn.java:62)
07-20 12:15:16.556 2056-2056/org.unrwa.edits W/System.err:     at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55)
07-20 12:15:16.557 2056-2056/org.unrwa.edits W/System.err:     at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:423)
07-20 12:15:16.557 2056-2056/org.unrwa.edits W/System.err:     at java.util.concurrent.FutureTask.run(FutureTask.java:237)
07-20 12:15:16.558 2056-2056/org.unrwa.edits W/System.err:     at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:269)
07-20 12:15:16.558 2056-2056/org.unrwa.edits W/System.err:     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
07-20 12:15:16.558 2056-2056/org.unrwa.edits W/System.err:     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
07-20 12:15:16.559 2056-2056/org.unrwa.edits W/System.err:     at java.lang.Thread.run(Thread.java:818)

Web 服务 API 的 URL,可以使用以下链接找到: https://api.trakt.tv/movies/popular?(page=%271%27)&limit=10&extended=full,images

PopularMoviesResponse POJO 类

公共类 PopularMoviesResponse {

private String OdataContext;
private List<PopularMovies> popularMovies = new ArrayList<PopularMovies>();


/**
 * 
 * @param OdataContext
 *     The @odata.context
 */
public void setOdataContext(String OdataContext) {
    this.OdataContext = OdataContext;
}

/**
 * 
 * @return
 *     The value
 */
public List<PopularMovies> getPopularMovies() {
    return popularMovies;
}

/**
 *
 * @param popularMovies
 */
public void setPopularMovies(List<PopularMovies> popularMovies) {
    this.popularMovies = popularMovies;
}

}

PopularMovies 类

@Generated("org.jsonschema2pojo") 公共类 PopularMovies {

@SerializedName("title")
@Expose
private String title;
@SerializedName("year")
@Expose
private long year;
@SerializedName("ids")
@Expose
private Ids ids;
@SerializedName("tagline")
@Expose
private String tagline;
@SerializedName("overview")
@Expose
private String overview;
@SerializedName("released")
@Expose
private String released;
@SerializedName("runtime")
@Expose
private long runtime;
@SerializedName("trailer")
@Expose
private String trailer;
@SerializedName("homepage")
@Expose
private String homepage;
@SerializedName("rating")
@Expose
private double rating;
@SerializedName("votes")
@Expose
private long votes;
@SerializedName("updated_at")
@Expose
private String updatedAt;
@SerializedName("language")
@Expose
private String language;
@SerializedName("available_translations")
@Expose
private List<String> availableTranslations = new ArrayList<String>();
@SerializedName("genres")
@Expose
private List<String> genres = new ArrayList<String>();
@SerializedName("certification")
@Expose
private String certification;
@SerializedName("images")
@Expose
private Images images;

/**
 * No args constructor for use in serialization
 * 
 */
public PopularMovies() {
}

/**
 * 
 * @param trailer
 * @param genres
 * @param availableTranslations
 * @param ids
 * @param votes
 * @param runtime
 * @param homepage
 * @param released
 * @param updatedAt
 * @param certification
 * @param title
 * @param overview
 * @param images
 * @param year
 * @param language
 * @param rating
 * @param tagline
 */
public PopularMovies(String title, long year, Ids ids, String tagline, String overview, String released, long runtime, String trailer, String homepage, double rating, long votes, String updatedAt, String language, List<String> availableTranslations, List<String> genres, String certification, Images images) {
    this.title = title;
    this.year = year;
    this.ids = ids;
    this.tagline = tagline;
    this.overview = overview;
    this.released = released;
    this.runtime = runtime;
    this.trailer = trailer;
    this.homepage = homepage;
    this.rating = rating;
    this.votes = votes;
    this.updatedAt = updatedAt;
    this.language = language;
    this.availableTranslations = availableTranslations;
    this.genres = genres;
    this.certification = certification;
    this.images = images;
}

/**
 * 
 * @return
 *     The title
 */
public String getTitle() {
    return title;
}

/**
 * 
 * @param title
 *     The title
 */
public void setTitle(String title) {
    this.title = title;
}

public PopularMovies withTitle(String title) {
    this.title = title;
    return this;
}

/**
 * 
 * @return
 *     The year
 */
public long getYear() {
    return year;
}

/**
 * 
 * @param year
 *     The year
 */
public void setYear(long year) {
    this.year = year;
}

public PopularMovies withYear(long year) {
    this.year = year;
    return this;
}

/**
 * 
 * @return
 *     The ids
 */
public Ids getIds() {
    return ids;
}

/**
 * 
 * @param ids
 *     The ids
 */
public void setIds(Ids ids) {
    this.ids = ids;
}

public PopularMovies withIds(Ids ids) {
    this.ids = ids;
    return this;
}

/**
 * 
 * @return
 *     The tagline
 */
public String getTagline() {
    return tagline;
}

/**
 * 
 * @param tagline
 *     The tagline
 */
public void setTagline(String tagline) {
    this.tagline = tagline;
}

public PopularMovies withTagline(String tagline) {
    this.tagline = tagline;
    return this;
}

/**
 * 
 * @return
 *     The overview
 */
public String getOverview() {
    return overview;
}

/**
 * 
 * @param overview
 *     The overview
 */
public void setOverview(String overview) {
    this.overview = overview;
}

public PopularMovies withOverview(String overview) {
    this.overview = overview;
    return this;
}

/**
 * 
 * @return
 *     The released
 */
public String getReleased() {
    return released;
}

/**
 * 
 * @param released
 *     The released
 */
public void setReleased(String released) {
    this.released = released;
}

public PopularMovies withReleased(String released) {
    this.released = released;
    return this;
}

/**
 * 
 * @return
 *     The runtime
 */
public long getRuntime() {
    return runtime;
}

/**
 * 
 * @param runtime
 *     The runtime
 */
public void setRuntime(long runtime) {
    this.runtime = runtime;
}

public PopularMovies withRuntime(long runtime) {
    this.runtime = runtime;
    return this;
}

/**
 * 
 * @return
 *     The trailer
 */
public String getTrailer() {
    return trailer;
}

/**
 * 
 * @param trailer
 *     The trailer
 */
public void setTrailer(String trailer) {
    this.trailer = trailer;
}

public PopularMovies withTrailer(String trailer) {
    this.trailer = trailer;
    return this;
}

/**
 * 
 * @return
 *     The homepage
 */
public String getHomepage() {
    return homepage;
}

/**
 * 
 * @param homepage
 *     The homepage
 */
public void setHomepage(String homepage) {
    this.homepage = homepage;
}

public PopularMovies withHomepage(String homepage) {
    this.homepage = homepage;
    return this;
}

/**
 * 
 * @return
 *     The rating
 */
public double getRating() {
    return rating;
}

/**
 * 
 * @param rating
 *     The rating
 */
public void setRating(double rating) {
    this.rating = rating;
}

public PopularMovies withRating(double rating) {
    this.rating = rating;
    return this;
}

/**
 * 
 * @return
 *     The votes
 */
public long getVotes() {
    return votes;
}

/**
 * 
 * @param votes
 *     The votes
 */
public void setVotes(long votes) {
    this.votes = votes;
}

public PopularMovies withVotes(long votes) {
    this.votes = votes;
    return this;
}

/**
 * 
 * @return
 *     The updatedAt
 */
public String getUpdatedAt() {
    return updatedAt;
}

/**
 * 
 * @param updatedAt
 *     The updated_at
 */
public void setUpdatedAt(String updatedAt) {
    this.updatedAt = updatedAt;
}

public PopularMovies withUpdatedAt(String updatedAt) {
    this.updatedAt = updatedAt;
    return this;
}

/**
 * 
 * @return
 *     The language
 */
public String getLanguage() {
    return language;
}

/**
 * 
 * @param language
 *     The language
 */
public void setLanguage(String language) {
    this.language = language;
}

public PopularMovies withLanguage(String language) {
    this.language = language;
    return this;
}

/**
 * 
 * @return
 *     The availableTranslations
 */
public List<String> getAvailableTranslations() {
    return availableTranslations;
}

/**
 * 
 * @param availableTranslations
 *     The available_translations
 */
public void setAvailableTranslations(List<String> availableTranslations) {
    this.availableTranslations = availableTranslations;
}

public PopularMovies withAvailableTranslations(List<String> availableTranslations) {
    this.availableTranslations = availableTranslations;
    return this;
}

/**
 * 
 * @return
 *     The genres
 */
public List<String> getGenres() {
    return genres;
}

/**
 * 
 * @param genres
 *     The genres
 */
public void setGenres(List<String> genres) {
    this.genres = genres;
}

public PopularMovies withGenres(List<String> genres) {
    this.genres = genres;
    return this;
}

/**
 * 
 * @return
 *     The certification
 */
public String getCertification() {
    return certification;
}

/**
 * 
 * @param certification
 *     The certification
 */
public void setCertification(String certification) {
    this.certification = certification;
}

public PopularMovies withCertification(String certification) {
    this.certification = certification;
    return this;
}

/**
 * 
 * @return
 *     The images
 */
public Images getImages() {
    return images;
}

/**
 * 
 * @param images
 *     The images
 */
public void setImages(Images images) {
    this.images = images;
}

public PopularMovies withImages(Images images) {
    this.images = images;
    return this;
}

}

JSON 响应

[ { "title": "黑暗骑士", "year": 2008, "ids": { "trakt": 120, “蛞蝓”:“黑暗骑士 2008”,“imdb”:“tt0468569”,“tmdb”:155 }, “标语”:“为什么这么严肃?”,“概述”:“蝙蝠侠提高了赌注 他对犯罪的战争。在 Lt. Jim Gordon 和地区的帮助下 哈维·登特律师,蝙蝠侠着手拆除剩下的 困扰街头的犯罪组织。伙伴关系证明 是有效的,但他们很快发现自己成为了统治的牺牲品 被恐惧者所熟知的犯罪主谋所引发的混乱 作为小丑的哥谭市民。", "发布": "2008-07-18", “运行时”:152,“预告片”:“http://youtube.com/watch?v=GVx5K8WfFJY”, “主页”:“http://thedarkknight.warnerbros.com/dvdsite/”,“评分”: 9.03781,“投票”:24887,“updated_at”:“2016-07-13T10:06:28.000Z”,“语言”:“en”,“available_translations”:[“en”,“de”,“fi”, "sv", “zh”、“ru”、“nl”、“it”、“fr”、“hu”、“da”、“es”、“tr”、“pt”、“cs”、 “pl”、“bg”、“he”、“sr”、“no”、“el”、“sk”、“ja”、“th”、“ko”、“uk”、 “fa”、“lv”、“ro”、“id”、“bs”、“ca”]、“流派”:[“动作”、“犯罪”、 “戏剧”,“惊悚片”],“认证”:“PG-13”,“图像”:{“同人画”: { “满的”: "https://walter.trakt.us/images/movies/000/000/120/fanarts/original/f7884a908e.jpg", “中等的”: "https://walter.trakt.us/images/movies/000/000/120/fanarts/medium/f7884a908e.jpg", “拇指”: "https://walter.trakt.us/images/movies/000/000/120/fanarts/thumb/f7884a908e.jpg" },“海报”:{“完整”: "https://walter.trakt.us/images/movies/000/000/120/posters/original/8369bf0d4a.jpg", “中等的”: "https://walter.trakt.us/images/movies/000/000/120/posters/medium/8369bf0d4a.jpg", “拇指”: “https://walter.trakt.us/images/movies/000/000/120/posters/thumb/8369bf0d4a.jpg” },“标志”:{“完整”: “https://walter.trakt.us/images/movies/000/000/120/logos/original/3e39105d34.png” }, "clearart": { "full": “https://walter.trakt.us/images/movies/000/000/120/cleararts/original/295bcec2cd.png” },“横幅”:{“完整”: “https://walter.trakt.us/images/movies/000/000/120/banners/original/7065417461.jpg” },“拇指”:{“完整”: “https://walter.trakt.us/images/movies/000/000/120/thumbs/original/6363cb8aeb.jpg” } } },

...

]

【问题讨论】:

  • 您确定您订阅了来自fetchPopularMoviesObservable 回报吗?能否请您展示您的那部分代码?
  • @Divers 我刚刚用代码更新了我的帖子。
  • 尝试在您的订阅中登录onError。有没有什么?还要检查是否调用了onCompleted
  • @Divers 我更新了我的帖子。 JSON 异常。我有以下网址:api.trakt.tv/movies/…
  • 不鼓励使用Observable.create。此外,您不需要 concatMap,只需映射:getPopularMovies(...).map(p -&gt; p.getPopularMovies())。如果仍然无效,请联系我们。

标签: android rx-java rx-android


【解决方案1】:

请尝试更改

public Observable&lt;PopularMoviesResponse&gt; getPopularMovies

public Observable&lt;List&lt;PopularMovies&gt;&gt; getPopularMovies

Android 你的方法然后:

public Observable<List<PopularMovies>> fetchPopularMovies(String trakt_api_version,
                                                          String trakt_api_key,
                                                          String page) {
    return movieService 
            .getPopularMovies(trakt_api_version, trakt_api_key, page)
}

UPD

只是为了确保您的 POJO 匹配 JSON,您可以使用 that service。在那个gist 你可以查看完整的结果。

【讨论】:

  • 和第二个sn-p的代码应该是什么?我可能会将其更改为 List !并且所有 POJO 都是使用该网站生成的。谢谢
  • @Androider 看来您的 API 已经返回了热门电影列表,因此您无需对其应用任何更改。
  • @Androider 实际上我不明白您为什么将 availableTranslations 字段放在 POJO 中。 JSON 中没有该字段。只需仔细检查您在 POJO 中的字段是否与 JSON 匹配,或者您可以使用我的要点。
  • 是的,它正在发送另一个参数进行翻译。我看到了你的要点。无论如何,问题出在数组/对象中。现在根据您要求的新修改。必须更改代码的第二个 sn-p。如何在 onNext() 中返回 List
  • @Androider 我已经在我的回答中发布了fetchPopularMovies 方法。明确一点,JSON 是已经的热门电影列表,你不需要修改它。
猜你喜欢
  • 2015-10-24
  • 2021-09-04
  • 2016-08-15
  • 2016-04-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-26
  • 1970-01-01
相关资源
最近更新 更多