我正在使用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” }},
...
答案 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中,您可以查看完整结果。