使用Retrofit和RxJava

时间:2016-07-20 08:42:03

标签: android rx-java rx-android

我正在使用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正常记录响应。但是在第二段代码中没有到达日志!有什么问题?

更新

这是订阅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,我得到了以下stacktrace:

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 class

公共课程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”:“黑暗骑士”,“年”:2008,“ids”:{“trakt”:120,   “slug”:“the-dark-knight-2008”,“imdb”:“tt0468569”,“tmdb”:155},   “标语”:“为什么如此严重?”,“概述”:“蝙蝠侠提高了赌注   他对犯罪的战争。在吉姆戈登和区中尉的帮助下   律师哈维登特,蝙蝠侠开始拆除剩下的   困扰街道的犯罪组织。合伙企业证明了这一点   为了有效,但他们很快发现自己成为统治者的牺牲品   被恐怖分子所知的一位正在崛起的犯罪主谋释放出来的混乱局面   Gotham的公民作为小丑。“,”发布“:”2008-07-18“,   “运行时”:152,“预告片”:“http://youtube.com/watch?v=GVx5K8WfFJY”,   “主页”:“http://thedarkknight.warnerbros.com/dvdsite/”,“评分”:   9.03781,“votes”:24887,“updated_at”:“2016-07-13T10:06:28.000Z”,“language”:“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”],“genres”:[“action”,“crime”,   “戏剧”,“惊悚片”,“认证”:“PG-13”,“图片”:{“fanart”:   {“满”:   “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”   },“poster”:{“full”:   “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”   },“logo”:{“full”:   “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”   },“banner”:{“full”:   “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”   }},

     

...

     

1 个答案:

答案 0 :(得分:2)

请尝试更改

public Observable<PopularMoviesResponse> getPopularMovies

public Observable<List<PopularMovies>> 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中,您可以查看完整结果。