我正在使用改造来点击返回json数组的网络api。我这样做是使用以下代码 -
Observable<MyJson[]> response = (Observable<MyJson[]>)mNetworkService.getReadyObserverable(mNetworkService.getNetworkServiceApi().getMyDataJsons(), MyJson.class, true, useCache);
mAirlineSubscription = response.subscribe(new Observer<MyJson[]>() {
@Override
public void onCompleted() {
Log.d(TAG, "getData completed..");
}
@Override
public void onError(Throwable e) {
Log.e(TAG, "onError: " + e.getLocalizedMessage());
}
@Override
public void onNext(MyJson[] myJsonData) {
//I want here json data one by one
}
但我的问题是json数据数组完全下载然后才下载
onNext
被调用。在这里,我希望在改装从onNext
json数组中下载第一个json对象时调用myData[]
并保持继续直到我的myData[]
的所有json对象都被下载。这样,我的UI在用户交互方面看起来会更具响应性和更好。
任何人都可以帮忙解决这个问题吗?
答案 0 :(得分:1)
您的服务应如下所示:
@GET("users/{username}/repos")
Observable<List<Repository>> publicRepositories(@Path("username") String username);
我的意思是,返回Observable<List<Something>>
答案 1 :(得分:1)
尽可能快地逐个接收元素?
不想等待下载所有内容?
解决方案是:使用注释@Streaming
声明改造界面的方法,并使用Observable<ResponseBody>
作为返回值。然后,使用flatMap()
,将ResponseBody
转换为POJO系列(Observable<TYPE>
)。
示例:强>
声明改造界面:
public interface HugeJsonApi {
String SERVICE_ENDPOINT = "https://raw.githubusercontent.com";
@Streaming
@GET("/zemirco/sf-city-lots-json/master/citylots.json")
Observable<ResponseBody> get();
}
使用它:
public void playHugeJsonSample() {
HugeJsonApi hugeJsonApi = RestUtils.createService(HugeJsonApi.class, HugeJsonApi.SERVICE_ENDPOINT);
Handler handler = new Handler(Looper.getMainLooper());
hugeJsonApi.get()
.flatMap(responseBody -> convertObjectsStream(responseBody, gson, Feature.class))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<Feature>() {
@Override
public void onStart() {
super.onStart();
request(1);
}
@Override
public void onNext(Feature feature) {
Log.i(TAG, gson.toJson(feature));
counter[0]++;
request(1);
}
@Override
public void onCompleted() {
Log.i(TAG, "onCompleted() called. Fetched elements:" + counter[0]);
}
@Override
public void onError(Throwable e) {
Log.e(TAG, "something went wrong", e);
}
});
}
@NonNull
private static <TYPE> Observable<TYPE> convertObjectsStream(ResponseBody responseBody, Gson gson, Class<TYPE> clazz) {
Type type = TypeToken.get(clazz).getType();
return Observable.create(SyncOnSubscribe.<JsonReader, TYPE>createStateful(
// initialize the reader
() -> {
try {
JsonReader reader = gson.newJsonReader(responseBody.charStream());
reader.beginObject();
return reader;
} catch (IOException e) {
e.printStackTrace();
RxJavaHooks.onError(e);
}
return null;
},
// read elements one by one
(reader, observer) -> {
if (reader == null) {
observer.onCompleted();
return null;
}
try {
if (reader.hasNext()) {
TYPE t = gson.fromJson(reader, type);
observer.onNext(t);
}
else {
observer.onCompleted();
}
} catch (IOException e) {
e.printStackTrace();
observer.onError(e);
}
return reader;
},
// close the reader
reader -> {
if (reader != null) {
try {
reader.close();
} catch (Exception e) {
e.printStackTrace();
RxJavaHooks.onError(e);
}
}
}
));
}
以下是可行的示例:
https://github.com/allco/RetrofitAndRxJava
它需要180 + Mb Json并将其解析为真正的流。
答案 2 :(得分:1)
我有同样的问题我解释它自己项目的基础,你应该使用 我的改装要求是
@GET("StudentApi/getAll")
Observable<List<Person>> getPersons();
我有一个运行服务器请求的接口,它有这个方法来运行getPersons()并返回json数组信息列表
Observable<Person> getAllPersons();
并且重要的部分是up方法的身体,并且应该像下面
@Override
public Observable<Person> getAllPersons() {
Observable<List<Person>> observable =
serviceGenerator.getService().getPersons();
return observable
.flatMap(new Function<List<Person>, Observable<Person>>() {
@Override
public Observable<Person> apply(List<Person> persons) throws Exception {
return Observable.fromIterable(persons);
}
});
}
我发现fromIterable方法一个接一个地返回json数组的对象 最后在一个活动中,我从诸如bellow
之类的向上方法中获取json对象public void getPersons(){
personsRepository.getAllPersons()
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribeWith(new DisposableObserver<Person>() {
@Override
public void onNext(Person value) {
Log.e("person info is",value.getpName() + value.getpFamily());
}
@Override
public void onError(Throwable throwable) {
Log.e("onError",throwable.toString());
}
@Override
public void onComplete() {
Log.e("onComplete","onComplete");
}
});
}
我希望有用:)