2016-08-08 40 views
0

Ich arbeite am Hochladen einer großen Datei auf einen Server auf Android, mit Retrofit mit RXJAVA.RX Androiden Observable + FileInputStream erhöht Heap-Speicher

Ich habe eine große Datei, und ich werde Datei zu einem kleinen Chunk Größe von Bytes Array nacheinander lesen, dann legte es auf den Server. Nach dem Erfolg werde ich den Fortschrittsbalken aktualisieren.

Aber das Problem ist, In meinem Fall werde ich 50 Chunks lesen, jede Chunk-Größe ist 6MB. Für die ersten 18 Chunks funktioniert es einwandfrei, der Heapspeicher wurde mit 6 MB belegt und der Fortschrittsbalken wurde reibungslos aktualisiert. Ab dem 19. Chunk wird der Fortschritt eingefroren, und die Heap-Größe wurde nach jeder Erstellung von Observable um 6 MB erhöht.

Wie auch immer, ich lade Datei noch erfolgreich auf den Server.

Hier ist mein Code:

private static void processUpload(File file, final ProgressUpdater updater) throws IOException, FileNotFoundException{ 
    final FileInputStream inputStream = new FileInputStream(file); 

    sCountSuccess = 0; 

    Observable<ResponseBody> responseBodyObservable = Observable.from(sUpload.getUploadChunk()) 
      .flatMap(new Func1<UploadChunk, Observable<ResponseBody>>() { 
       @Override 
       public Observable<ResponseBody> call(UploadChunk uploadChunk) { 
        int bytesRead = -1; 
        try { 
         byte[] temp = new byte[chunkSize]; 
         bytesRead = inputStream.read(temp); 
         if (bytesRead != -1) { 

          byte[] finalBuffer; 
          if (temp.length > bytesRead) 
          { 
           finalBuffer = Arrays.copyOf(temp, bytesRead); 
          } 
          else 
          { 
           finalBuffer = temp; 
          } 

          RequestBody requestBody = RequestBody.create(MediaType.parse(""), finalBuffer); 
          Log.d("UPLOAD_ID", uploadChunk.getUrl()); 
          Observable<ResponseBody> responseBodyObservable = sNetworkResources.putVideo(uploadChunk.getUrl(), requestBody); 

          return responseBodyObservable; 
         } 
        } catch (Exception e) { 
         Log.e("UPLOAD_ERROR", e.getMessage()); 
        } finally { 
         if(inputStream != null && bytesRead == -1) { 
          try { 
           inputStream.close(); 
          } catch (IOException e) { 
           e.printStackTrace(); 
          } 
         } 
        } 
        return null; 
       } 
      .subscribeOn(Schedulers.io()) 
      .observeOn(AndroidSchedulers.mainThread()); 

    responseBodyObservable.subscribe(new Subscriber<ResponseBody>() { 
       @Override 
       public void onCompleted() { 
         updater.onProgressFinish(); 
         commitUpload(); 
//      } 
       } 

       @Override 
       public void onError(Throwable e) { 
       } 

       @Override 
       public void onNext(ResponseBody data) { 
        // update 
        sCountSuccess++; 
        updater.onProgressUpdate(sCountSuccess); 
       } 
      }); 
} 

Antwort

0

This Beitrag auf der Seite Retrofit GitHub sagt, wenn Sie die @Multipart Anmerkung auf Ihrer Schnittstelle verwenden Sie nicht zu Klumpen, den Strom selbst brauchen sollte:

Nachrüsten wird Multipart Teile Körper direkt an das Netzwerk, so dass die Tatsache, dass Sie einen großen Körper senden sollte kein OOM verursachen, es sei denn, Sie verursachen es irgendwie gepuffert werden.

Ihre Schnittstelle wie folgt aussehen könnte:

@Multipart 
@PUT(VIDEO_URL) 
Observable<ResponseBody> putVideo(@Url String videoUrl, @Part("file") RequestBody requestBody);