Retrofit 对象返回为 null
Retrofit object returned as null
我已经为 return 一些对象构建了 RetroFitService。在 MainActivity 中,我只需单击一下按钮即可调用该服务。我似乎得到了某种对象,但我不觉得它实际上是从我指定的 REST API 中 return 编辑的。它显示在调试器中,但其属性为空:
bFetch.setOnClickListener(v -> {
v.startAnimation(AnimationUtils.loadAnimation(this, R.anim.image_click));
RetrofitService service = ServiceFactory.createRetrofitService(RetrofitService.class, RetrofitService.SERVICE_ENDPOINT);
service.getPosts()
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber < Post > () {
@Override
public final void onCompleted() {
Log.e("RetrofitService", "Retrofit Request Completed!");
}
@Override
public final void onError(Throwable e) {
Log.e("RetrofitService", e.getMessage());
}
@Override
public final void onNext(Post post) {
if (post != null) {
// TODO: Some object is returned but its properties are null
Log.e("RetrofitService", "Returned objects: " + post);
Log.e("RetrofitService", "Object Id: " + post.getObjectId());
mCardAdapter.addData(post);
} else {
Log.e("RetrofitService", "Object returned is null.");
}
}
});
});
}
服务:
public interface RetrofitService {
String SERVICE_ENDPOINT = "https://parseapi.back4app.com/";
@Headers({
"X-Parse-Application-Id: asdf",
"X-Parse-REST-API-Key: asdf"
})
@GET("/classes/Post")
Observable < Post > getPosts();
/*curl -X GET \
-H "X-Parse-Application-Id: asdf" \
-H "X-Parse-REST-API-Key: asdf" \
https://parseapi.back4app.com/classes/Post*/
}
卷曲效果很好。我没有收到任何错误。可能出了什么问题?是不是我的 @GET
方法不正确?`
为了完成,这里是 ServiceFactory class:
public class ServiceFactory {
/**
* Creates a retrofit service from an arbitrary class (clazz)
* @param clazz Java interface of the retrofit service
* @param endPoint REST endpoint url
* @return retrofit service with defined endpoint
*/
public static <T> T createRetrofitService(final Class<T> clazz, final String endPoint) {
final RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint(endPoint)
.build();
T service = restAdapter.create(clazz);
return service;
}
}
还有我的 build.gradle 因为我知道所有不同的 Retrofit 版本都存在不一致:
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:25.3.1'
compile 'com.android.support.constraint:constraint-layout:1.0.2'
testCompile 'junit:junit:4.12'
/* ReactiveX */
compile 'io.reactivex:rxjava:1.0.17'
compile 'io.reactivex:rxandroid:0.23.0'
/* Retrofit */
compile 'com.squareup.retrofit:retrofit:1.9.0'
/* OkHttp3 */
compile 'com.squareup.okhttp3:okhttp:3.8.1'
/* RecylerView */
compile 'com.android.support:recyclerview-v7:25.3.1'
/* CardView */
compile 'com.android.support:cardview-v7:25.3.1'
/* Parse */
compile 'com.parse:parse-android:1.13.0'
}
Post Class:
public class Post implements Serializable {
private static final String CLASS_NAME = "Post";
private String objectId;
private String text;
public Post(String objectId) {
this.setObjectId(objectId);
}
public static String getClassName() {
return CLASS_NAME;
}
public String getObjectId() {
return objectId;
}
private void setObjectId(String objectId) {
this.objectId = objectId;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
卷曲响应:
> https://parseapi.back4app.com/classes/Post/
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 259 100 259 0 0 360 0 --:--:-- --:--:-- --:--:-- 395{"results":[{"objectId":"ktEfgr1pFt","text":"Hello World.","createdAt":"2017-08-14T14:07:52.826Z","updatedAt":"2017-08-14T14:07:52.826Z"},{"objectId":"Mmh8l9gjCk","text":"Hello?","createdAt":"2017-08-14T15:19:01.515Z","updatedAt":"2017-08-14T15:19:03.743Z"}]}
最终更新: 我更改了 RetrofitService
的 onNext()
方法以传递到 CardAdapter,尽管此处未显示并且超过了问题的范围。
@Override
public final void onNext(PostResponse postResponse) {
if (postResponse != null) {
// TODO: Some object is returned but its properties are null
Log.e("RetrofitService", "Objects successfully added to RecyclerView Adapter.");
Log.e("RetrofitService", "Returned objects: " + postResponse.getResults());
Log.e("RetrofitService", "Text " + postResponse.getResults().get(0).getText());
mCardAdapter.addData(postResponse);
//
} else {
Log.e("RetrofitService", "Object returned is null.");
}
}
尝试在RetrofitService
中使用以下class
@GET("/classes/Post")
Observable <PostResponse> getPosts();
PostResponse 包装器 class
public class PostResponse {
private List<Post> results;
public List<Post> getResults() {
return results;
}
public void setResults(List<Post> results) {
this.results = results;
}
}
根据您问题的更新,您收到的不是单个对象,而是包含 Post
个对象集合的对象。
所以你需要再加一个class:
public class Results {
List<Post> results = ArrayList<>()
}
然后将你的API接口方法更新为return Observable<Results>
:
Observable <Results> getPosts();
在订阅中,您最终可以使用 results
字段访问 Result
对象,其中包含 Post
个对象的集合。
一个小错误是你的端点基础 URL 有尾部斜杠:
String SERVICE_ENDPOINT = "https://parseapi.back4app.com/";
同时你的 API 方法在路径的开头有斜杠:
@GET("/classes/Post")
Observable < Post > getPosts();
据我所知 进行改造时,您应该在端点地址中使用尾部斜线或在 API 方法中使用起始斜线,否则这可能无法正常工作。
这个应该是正确的:
String SERVICE_ENDPOINT = "https://parseapi.back4app.com"; // No slash here
@GET("/classes/Post") // Keep slash here, or vice verse
Observable<Results> getPosts();
只是对您的依赖项部分的一些评论:
您使用 io.reactivex:rxandroid
版本 0.23.0
而最新稳定版是 1.2.1
是否有任何特殊原因?
你不需要 io.reactivex:rxjava:1.0.17
依赖,因为 retrofit 1.9.0 已经依赖 rxjava 1.0.0
我已经为 return 一些对象构建了 RetroFitService。在 MainActivity 中,我只需单击一下按钮即可调用该服务。我似乎得到了某种对象,但我不觉得它实际上是从我指定的 REST API 中 return 编辑的。它显示在调试器中,但其属性为空:
bFetch.setOnClickListener(v -> {
v.startAnimation(AnimationUtils.loadAnimation(this, R.anim.image_click));
RetrofitService service = ServiceFactory.createRetrofitService(RetrofitService.class, RetrofitService.SERVICE_ENDPOINT);
service.getPosts()
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber < Post > () {
@Override
public final void onCompleted() {
Log.e("RetrofitService", "Retrofit Request Completed!");
}
@Override
public final void onError(Throwable e) {
Log.e("RetrofitService", e.getMessage());
}
@Override
public final void onNext(Post post) {
if (post != null) {
// TODO: Some object is returned but its properties are null
Log.e("RetrofitService", "Returned objects: " + post);
Log.e("RetrofitService", "Object Id: " + post.getObjectId());
mCardAdapter.addData(post);
} else {
Log.e("RetrofitService", "Object returned is null.");
}
}
});
});
}
服务:
public interface RetrofitService {
String SERVICE_ENDPOINT = "https://parseapi.back4app.com/";
@Headers({
"X-Parse-Application-Id: asdf",
"X-Parse-REST-API-Key: asdf"
})
@GET("/classes/Post")
Observable < Post > getPosts();
/*curl -X GET \
-H "X-Parse-Application-Id: asdf" \
-H "X-Parse-REST-API-Key: asdf" \
https://parseapi.back4app.com/classes/Post*/
}
卷曲效果很好。我没有收到任何错误。可能出了什么问题?是不是我的 @GET
方法不正确?`
为了完成,这里是 ServiceFactory class:
public class ServiceFactory {
/**
* Creates a retrofit service from an arbitrary class (clazz)
* @param clazz Java interface of the retrofit service
* @param endPoint REST endpoint url
* @return retrofit service with defined endpoint
*/
public static <T> T createRetrofitService(final Class<T> clazz, final String endPoint) {
final RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint(endPoint)
.build();
T service = restAdapter.create(clazz);
return service;
}
}
还有我的 build.gradle 因为我知道所有不同的 Retrofit 版本都存在不一致:
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:25.3.1'
compile 'com.android.support.constraint:constraint-layout:1.0.2'
testCompile 'junit:junit:4.12'
/* ReactiveX */
compile 'io.reactivex:rxjava:1.0.17'
compile 'io.reactivex:rxandroid:0.23.0'
/* Retrofit */
compile 'com.squareup.retrofit:retrofit:1.9.0'
/* OkHttp3 */
compile 'com.squareup.okhttp3:okhttp:3.8.1'
/* RecylerView */
compile 'com.android.support:recyclerview-v7:25.3.1'
/* CardView */
compile 'com.android.support:cardview-v7:25.3.1'
/* Parse */
compile 'com.parse:parse-android:1.13.0'
}
Post Class:
public class Post implements Serializable {
private static final String CLASS_NAME = "Post";
private String objectId;
private String text;
public Post(String objectId) {
this.setObjectId(objectId);
}
public static String getClassName() {
return CLASS_NAME;
}
public String getObjectId() {
return objectId;
}
private void setObjectId(String objectId) {
this.objectId = objectId;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
卷曲响应:
> https://parseapi.back4app.com/classes/Post/
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 259 100 259 0 0 360 0 --:--:-- --:--:-- --:--:-- 395{"results":[{"objectId":"ktEfgr1pFt","text":"Hello World.","createdAt":"2017-08-14T14:07:52.826Z","updatedAt":"2017-08-14T14:07:52.826Z"},{"objectId":"Mmh8l9gjCk","text":"Hello?","createdAt":"2017-08-14T15:19:01.515Z","updatedAt":"2017-08-14T15:19:03.743Z"}]}
最终更新: 我更改了 RetrofitService
的 onNext()
方法以传递到 CardAdapter,尽管此处未显示并且超过了问题的范围。
@Override
public final void onNext(PostResponse postResponse) {
if (postResponse != null) {
// TODO: Some object is returned but its properties are null
Log.e("RetrofitService", "Objects successfully added to RecyclerView Adapter.");
Log.e("RetrofitService", "Returned objects: " + postResponse.getResults());
Log.e("RetrofitService", "Text " + postResponse.getResults().get(0).getText());
mCardAdapter.addData(postResponse);
//
} else {
Log.e("RetrofitService", "Object returned is null.");
}
}
尝试在RetrofitService
中使用以下class@GET("/classes/Post")
Observable <PostResponse> getPosts();
PostResponse 包装器 class
public class PostResponse {
private List<Post> results;
public List<Post> getResults() {
return results;
}
public void setResults(List<Post> results) {
this.results = results;
}
}
根据您问题的更新,您收到的不是单个对象,而是包含 Post
个对象集合的对象。
所以你需要再加一个class:
public class Results {
List<Post> results = ArrayList<>()
}
然后将你的API接口方法更新为return Observable<Results>
:
Observable <Results> getPosts();
在订阅中,您最终可以使用 results
字段访问 Result
对象,其中包含 Post
个对象的集合。
一个小错误是你的端点基础 URL 有尾部斜杠:
String SERVICE_ENDPOINT = "https://parseapi.back4app.com/";
同时你的 API 方法在路径的开头有斜杠:
@GET("/classes/Post")
Observable < Post > getPosts();
据我所知 进行改造时,您应该在端点地址中使用尾部斜线或在 API 方法中使用起始斜线,否则这可能无法正常工作。
这个应该是正确的:
String SERVICE_ENDPOINT = "https://parseapi.back4app.com"; // No slash here
@GET("/classes/Post") // Keep slash here, or vice verse
Observable<Results> getPosts();
只是对您的依赖项部分的一些评论:
您使用 io.reactivex:rxandroid
版本 0.23.0
而最新稳定版是 1.2.1
是否有任何特殊原因?
你不需要 io.reactivex:rxjava:1.0.17
依赖,因为 retrofit 1.9.0 已经依赖 rxjava 1.0.0