rx android observable + FileInputStream增加堆内存

时间:2016-08-08 02:52:11

标签: android heap-memory observable rx-android

我正在使用rxjava改造将一个大文件上传到android上的服务器。

我有一个大文件,我会将文件读取到一小块字节数组,然后将它放到服务器上。成功后,我会更新进度条。

但问题是,在我的情况下,我将读取50个块,每个块大小为6MB。对于前18个块,它工作正常,堆内存分配6MB,进度条平滑更新。但是从第19个块开始,进度将被冻结,并且每次创建Observable后堆大小分配越来越多。

无论如何,我仍然成功地将文件上传到服务器。

这是我的代码:

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

1 个答案:

答案 0 :(得分:0)

Retrofit GitHub页面上的

This帖子说如果你在界面上使用@Multipart注释,你不需要自己对流进行分块:

  

Retrofit会将Multipart部分主体直接传输到网络,因此您发送大型主体不会导致OOM,除非您以某种方式缓冲它。

您的界面可能如下所示:

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