2016-09-05 57 views
5

Tôi đang sử dụng trang bị thêm để truy cập api mạng của mình để trả về mảng json. Tôi làm như vậy sử dụng sau số-Nhận đối tượng JSON từng cái một từ mảng JSON trong Android bằng Retrofit và RxJava

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 
      } 

Nhưng vấn đề của tôi là mảng dữ liệu json được tải về hoàn toàn và sau đó chỉ onNext được gọi. Ở đây tôi muốn onNext nên được gọi khi trang bị thêm tải xuống đối tượng json đầu tiên từ mảng json myData[] và tiếp tục cho đến khi tất cả các đối tượng json của tôi được tải xuống myData[]. Bằng cách này, giao diện người dùng của tôi sẽ trông nhạy hơn và tốt hơn về tương tác của người dùng.

Có ai có thể giúp khắc phục sự cố này không?

+2

Retrofit không hỗ trợ điều này trong hộp - tùy chỉnh 'CallAdapter' và' Converter' là cần thiết. Cả hai đều được yêu cầu - trong CallAdapter, luồng của 'ResponseBody' phải được xử lý (nhận các mục mảng riêng lẻ) VÀ chuyển đổi thành các đối tượng java và Trình chuyển đổi chỉ cần chuyển các kết quả đó như là (noop). Đầu tiên, điều này mâu thuẫn với thiết kế của nó, nơi mà CallAdapter và Converter là các thực thể độc lập. Thứ hai, việc thực hiện sẽ không độc hại và dài dòng - phân tích cú pháp luồng json, rxjava backpressure vv - tôi đề nghị bạn tìm một giải pháp khác cho vấn đề - phân trang dữ liệu, phản hồi nhỏ hơn, –

Trả lời

1

dịch vụ của bạn sẽ trông như thế này:

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

Ý tôi là, trả lại một Observable<List<Something>>

+1

OP muốn liệt kê các mục ngay sau khi chúng có sẵn - 'Quan sát ', cách tiếp cận này vẫn tải xuống tất cả phản hồi và sau đó phát hành thông báo đơn - 'Quan sát >' –

0

yếu tố nhận từng người một, càng nhanh càng tốt?
Bạn không muốn đợi khi mọi thứ sẽ được tải xuống?

Giải pháp là: Khai báo phương thức của giao diện trang bị thêm bằng chú thích @Streaming và sử dụng Observable<ResponseBody> làm giá trị trả về. Và sau đó, bằng cách sử dụng flatMap(), chuyển đổi ResponseBody thành chuỗi POJO (Observable<TYPE>).

Ví dụ:

  1. Declare trang bị thêm giao diện:

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

  2. Sử dụng nó như thế:

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

Dưới đây là hoàn toàn khả thi dụ:

https://github.com/allco/RetrofitAndRxJava

Phải mất 180 + Mb Json và phân tích nó như một dòng suối thật.

+0

Tôi sẽ thử giải pháp này và cập nhật tại đây sớm. – AndroDev

+0

@AndroDev, bạn có phản hồi gì không? –

+0

chưa được thử. đang đi nghỉ. chắc chắn sẽ cập nhật cho bạn khi tôi kiểm tra. – AndroDev

1

tôi đã cùng một câu hỏi tôi giải thích nó cơ sở của dự án riêng, bạn nên sử dụng yêu cầu trang bị thêm của tôi là

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

và tôi có một giao diện để chạy yêu cầu máy chủ và nó có phương pháp này cho getPersons run() và trở lại danh sách các mảng json thông tin người

Observable<Person> getAllPersons(); 

và một phần quan trọng là cơ thể lên phương pháp và cần thích dưới đây

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

tôi thấy rằng đối tượng fromIterable phương pháp lợi nhuận của mảng json từng người một và cuối cùng trong một hoạt động tôi nhận được đối tượng json từ lên các phương pháp như dưới đây

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

tôi hy vọng là hữu ích :)

Các vấn đề liên quan