2017-01-27 25 views
12
@Streaming 
@GET 
Call<ResponseBody> downloadSong(@Url String url); 

Вышеуказанный код используется для асинхронного скачивания файла с использованием модификации. Я хочу получить прогресс загрузки, если есть какая-либо возможность приостановки/возобновления пожалуйста, ответьте тожеМожно ли показывать индикатор выполнения при загрузке через Retrofit 2 Asynchronous?

ответ

11

Atlast я получил мой ответ,

Для этого нужно использовать rxjava вместе с модифицированной

DownloadProgressListener. Java

public interface DownloadProgressListener { 
     void update(long bytesRead, long contentLength, boolean done); } 

DownloadProgressResponseBody.java

public class DownloadProgressResponseBody extends ResponseBody { 

    private ResponseBody responseBody; 
    private DownloadProgressListener progressListener; 
    private BufferedSource bufferedSource; 

    public DownloadProgressResponseBody(ResponseBody responseBody, 
             DownloadProgressListener progressListener) { 
     this.responseBody = responseBody; 
     this.progressListener = progressListener; 
    } 

    @Override 
    public MediaType contentType() { 
     return responseBody.contentType(); 
    } 

    @Override 
    public long contentLength() { 
     return responseBody.contentLength(); 
    } 

    @Override 
    public BufferedSource source() { 
     if (bufferedSource == null) { 
      bufferedSource = Okio.buffer(source(responseBody.source())); 
     } 
     return bufferedSource; 
    } 

    private Source source(Source source) { 
     return new ForwardingSource(source) { 
      long totalBytesRead = 0L; 

      @Override 
      public long read(Buffer sink, long byteCount) throws IOException { 
       long bytesRead = super.read(sink, byteCount); 
       // read() returns the number of bytes read, or -1 if this source is exhausted. 
       totalBytesRead += bytesRead != -1 ? bytesRead : 0; 

       if (null != progressListener) { 
        progressListener.update(totalBytesRead, responseBody.contentLength(), bytesRead == -1); 
       } 
       return bytesRead; 
      } 
     }; 

    } 
} 

DownloadProgressInterceptor.java

public class DownloadProgressInterceptor implements Interceptor { 

    private DownloadProgressListener listener; 

    public DownloadProgressInterceptor(DownloadProgressListener listener) { 
     this.listener = listener; 
    } 

    @Override 
    public Response intercept(Chain chain) throws IOException { 
     Response originalResponse = chain.proceed(chain.request()); 

     return originalResponse.newBuilder() 
       .body(new DownloadProgressResponseBody(originalResponse.body(), listener)) 
       .build(); 
    } 
} 

Download.java

public class Download implements Parcelable { 

    private int progress; 
    private long currentFileSize; 
    private long totalFileSize; 

    public int getProgress() { 
     return progress; 
    } 

    public void setProgress(int progress) { 
     this.progress = progress; 
    } 

    public long getCurrentFileSize() { 
     return currentFileSize; 
    } 

    public void setCurrentFileSize(long currentFileSize) { 
     this.currentFileSize = currentFileSize; 
    } 

    public long getTotalFileSize() { 
     return totalFileSize; 
    } 

    public void setTotalFileSize(long totalFileSize) { 
     this.totalFileSize = totalFileSize; 
    } 

    @Override 
    public int describeContents() { 
     return 0; 
    } 

    @Override 
    public void writeToParcel(Parcel dest, int flags) { 
     dest.writeInt(this.progress); 
     dest.writeLong(this.currentFileSize); 
     dest.writeLong(this.totalFileSize); 
    } 

    public Download() { 
    } 

    protected Download(Parcel in) { 
     this.progress = in.readInt(); 
     this.currentFileSize = in.readLong(); 
     this.totalFileSize = in.readLong(); 
    } 

    public static final Parcelable.Creator<Download> CREATOR = new Parcelable.Creator<Download>() { 
     @Override 
     public Download createFromParcel(Parcel source) { 
      return new Download(source); 
     } 

     @Override 
     public Download[] newArray(int size) { 
      return new Download[size]; 
     } 
    }; 
} 

DownloadService.java

public interface DownloadService { 
     @Streaming 
     @GET 
     Observable<ResponseBody> download(@Url String url); 
    } 

    public class DownloadAPI { 
     private static final String TAG = "DownloadAPI"; 
     private static final int DEFAULT_TIMEOUT = 15; 
     public Retrofit retrofit; 

DownloadAPI.java

public DownloadAPI(String url, DownloadProgressListener listener) { 

      DownloadProgressInterceptor interceptor = new DownloadProgressInterceptor(listener); 

      OkHttpClient client = new OkHttpClient.Builder() 
        .addInterceptor(interceptor) 
        .retryOnConnectionFailure(true) 
        .connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS) 
        .build(); 


      retrofit = new Retrofit.Builder() 
        .baseUrl(url) 
        .client(client) 
        .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) 
        .build(); 
     } 

     public void downloadAPK(@NonNull String url, final File file, Subscriber subscriber) { 
      Log.d(TAG, "downloadAPK: " + url); 

      retrofit.create(DownloadService.class) 
        .download(url) 
        .subscribeOn(Schedulers.io()) 
        .unsubscribeOn(Schedulers.io()) 
        .map(new Func1<ResponseBody, InputStream>() { 
         @Override 
         public InputStream call(ResponseBody responseBody) { 
          return responseBody.byteStream(); 
         } 
        }) 
        .observeOn(Schedulers.computation()) 
        .doOnNext(new Action1<InputStream>() { 
         @Override 
         public void call(InputStream inputStream) { 
          try { 
           FileUtils.writeFile(inputStream, file); 
          } catch (IOException e) { 
           e.printStackTrace(); 
           throw new CustomizeException(e.getMessage(), e); 
          } 
         } 
        }) 
        .observeOn(AndroidSchedulers.mainThread()) 
        .subscribe(subscriber); 
     } 


    } 

Использование

DownloadProgressListener listener = new DownloadProgressListener() { 
      @Override 
      public void update(long bytesRead, long contentLength, boolean done) { 
       Download download = new Download(); 
       download.setTotalFileSize(contentLength); 
       download.setCurrentFileSize(bytesRead); 
       int progress = (int) ((bytesRead * 100)/contentLength); 
       download.setProgress(progress); 

       sendNotification(download); 
      } 
     }; 
     File outputFile = new File(Environment.getExternalStoragePublicDirectory 
       (Environment.DIRECTORY_DOWNLOADS), "file.apk"); 
     String baseUrl = StringUtils.getHostName(apkUrl); 

     new DownloadAPI(baseUrl, listener).downloadAPK(apkUrl, outputFile, new Subscriber() { 
      @Override 
      public void onCompleted() { 
       downloadCompleted(); 
      } 

      @Override 
      public void onError(Throwable e) { 
       e.printStackTrace(); 
       downloadCompleted(); 
       Log.e(TAG, "onError: " + e.getMessage()); 
      } 

      @Override 
      public void onNext(Object o) { 

      } 
     }); 
+3

, поэтому я читаю учебники по rxjava, чтобы применить этот подход, надеюсь, вы получили хороший перформанс, который загружает прогресс для нескольких уведомлений? –

+1

@Bincy Baby Пожалуйста, расскажите, какие все зависимости я должен добавить. –

+0

вы должны добавить retrofit и rxjava 1 к вашему проекту –