Get JSON object one by one from Android JSON array using Retrofit and RxJava

I use a modification to get into my api network, which returns a json array. I do this using the following code -

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 } 

But my problem is that the json dataset is loaded completely and then only onNext is called. Here, I want onNext to be called when retrofit loads the first json object from the myData[] json array and continues to work until all of my myData[] json objects have been loaded. Thus, my user interface will look more responsive and better in terms of user interaction.

Can anyone help fix this?

+5
source share
3 answers

Your service should look like this:

 @GET("users/{username}/repos") Observable<List<Repository>> publicRepositories(@Path("username") String username); 

I mean, return a Observable<List<Something>>

+1
source

I have the same question, I explain it with the basis of my own project, you should use my request for modification

 @GET("StudentApi/getAll") Observable<List<Person>> getPersons(); 

and I have an interface to run a server request, and it has this method to run getPersons () and return a list of json array of face information

 Observable<Person> getAllPersons(); 

, and the important part is the body up method, and it should look below

 @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); } }); } 

I found that the fromIterable method returns json array objects one by one, and finally, in action, I get json objects from the methods at the top, for example, below.

 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"); } }); } 

I hope this is helpful :)

+1
source

Getting items One by one, as fast as possible?
Do not want to wait until everything is loaded?

Solution: declare a modified interface method with @Streaming annotation and use Observable<ResponseBody> as the return value. And then using flatMap() , convert the ResponseBody to a POJO sequence ( Observable<TYPE> ).

Example:

  • Declare an interface for retooling:

     public interface HugeJsonApi { String SERVICE_ENDPOINT = "https://raw.githubusercontent.com"; @Streaming @GET("/zemirco/sf-city-lots-json/master/citylots.json") Observable<ResponseBody> get(); } 
  • Use it like this:

     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); } } } )); } 

Here is an example of work:

https://github.com/allco/RetrofitAndRxJava

It takes 180+ MB of Json and parses it as a real thread.

0
source

All Articles