我正在使用改造来下载android中的大文件。 API将文件作为字节数组返回,我已经添加了@Streaming注释,但我仍然收到错误。
我能做些什么来解决它?
下载期间发生的错误。
我的代码:
//Retrofi api method
@Streaming
@GET(POOL + "DmListarDocsProjZip/{IdProjetct}")
Call<byte[]> dmListarDocsProjZip(@Path("IdProjetct") int idProject);
//THIS CODE IS INSIDE AN IntentService
//consuming method
private byte[] buscarDocs(int idProjeto) {
try {
Call<byte[]> call = mApi.dmListarDocsProjZip(idProject);
Response<byte[]> response = call.execute();// The OutOfMemoryError is ocurring in here
return response.body();
} catch (IOException e) {
Log.e("buscarDocs", "dmListarDocsProjetoZip");
} catch (Exception e) {
verificarSeSessaoExpirou(e);
}
return null;
}
Process: br.gov.sp.prodesp.viafacilbombeiros, PID: 27184
java.lang.OutOfMemoryError: Failed to allocate a 68706640 byte allocation with 16777120 free bytes and 203MB until OOM
at java.util.ArrayList.add(ArrayList.java:118)
at com.google.gson.internal.bind.ArrayTypeAdapter.read(ArrayTypeAdapter.java:73)
at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:37)
at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:25)
at retrofit2.ServiceMethod.toResponse(ServiceMethod.java:117)
at retrofit2.OkHttpCall.parseResponse(OkHttpCall.java:211)
at retrofit2.OkHttpCall.execute(OkHttpCall.java:174)
at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall.execute(ExecutorCallAdapterFactory.java:89)
at br.gov.sp.prodesp.viafacilbombeiros.model.DownloadDadosIntentService.buscarDocs(DownloadDadosIntentService.java:253)
at br.gov.sp.prodesp.viafacilbombeiros.model.DownloadDadosIntentService.access$300(DownloadDadosIntentService.java:61)
at br.gov.sp.prodesp.viafacilbombeiros.model.DownloadDadosIntentService$1.onNext(DownloadDadosIntentService.java:215)
at br.gov.sp.prodesp.viafacilbombeiros.model.DownloadDadosIntentService$1.onNext(DownloadDadosIntentService.java:189)
at rx.observers.SafeSubscriber.onNext(SafeSubscriber.java:139)
at retrofit2.adapter.rxjava.OperatorMapResponseToBodyOrError$1.onNext(OperatorMapResponseToBodyOrError.java:41)
at retrofit2.adapter.rxjava.OperatorMapResponseToBodyOrError$1.onNext(OperatorMapResponseToBodyOrError.java:38)
at retrofit2.adapter.rxjava.RxJavaCallAdapterFactory$RequestArbiter.request(RxJavaCallAdapterFactory.java:173)
at rx.Subscriber.setProducer(Subscriber.java:209)
at rx.Subscriber.setProducer(Subscriber.java:205)
at rx.Subscriber.setProducer(Subscriber.java:205)
at retrofit2.adapter.rxjava.RxJavaCallAdapterFactory$CallOnSubscribe.call(RxJavaCallAdapterFactory.java:152)
at retrofit2.adapter.rxjava.RxJavaCallAdapterFactory$CallOnSubscribe.call(RxJavaCallAdapterFactory.java:138)
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:50)
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
at rx.Observable.subscribe(Observable.java:8553)
at rx.Observable.subscribe(Observable.java:8520)
at br.gov.sp.prodesp.viafacilbombeiros.model.DownloadDadosIntentService.onHandleIntent(DownloadDadosIntentService.java:124)
at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:65)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:145)
at android.os.HandlerThread.run(HandlerThread.java:61)
答案 0 :(得分:0)
您必须将此大文件保存到磁盘。看起来你正在使用@Streaming下载它(如推荐的那样),但你将它分配给内存,所以@Streaming有点无用。 对于大文件,您需要使用注释,以便在下载过程中避免内存泄漏,但您还需要将文件保存到磁盘,因此您不需要分配那么多内存。
答案 1 :(得分:0)
您的OkHttpClient是否将LoggingInterceptor添加到日志正文? 如果尝试下载大文件,则会将所有正文保存在内存中以备日志。 让OOM很容易。
如果要记录正文,请尝试删除或仅记录基本或标头,然后重试。
如果您的代码是这样的。
val logging = HttpLoggingInterceptor()
logging.level = HttpLoggingInterceptor.Level.BODY
val client = OkHttpClient.Builder()
.addInterceptor(logging)
.build()
尝试一下。
val logging = HttpLoggingInterceptor()
logging.level = HttpLoggingInterceptor.Level.NONE
val client = OkHttpClient.Builder()
.addInterceptor(logging)
.build()