우찬쓰 개발블로그
안드로이드 retrofit2 + rxjava2 로 파일 다운로드 progress 표시하기 본문
반응형
큰 파일을 다운로드하여 안드로이드 저장소에 넣어야 하는 경우, 유저의 네트워크 상황에따라 오래 걸리는 경우가 있을 수 있다.
이런 경우를 대비하여 유저 편의성을 위해 progress bar를 표시해주어야 하는데, 직접 하나하나 구현해 보도록 하자.
1. 먼저 간단하게 Retrofit Service 클래스를 만든다.
interface RetrofitService {
/**
* 파일 요청.
*/
@GET("테스트 파일이 있는 url path")
fun requestFile(): Flowable<ResponseBody>
}
가볍게 하기위해 API 요청시 필요한 데이터는 없다고 가정한다.
2. 이 파일을 내려받는 과정에서의 진행도를 노티받기 위하여 ResponseBody를 상속받은 클래스를 하나 만들어야한다.
class ProgressResponseBody(val responseBody: ResponseBody, val onAttachmentDownloadUpdate: (Int) -> Unit) : ResponseBody() {
private var bufferedSource = Okio.buffer(source(responseBody.source()))
override fun contentLength(): Long {
return responseBody.contentLength()
}
override fun contentType(): MediaType? {
return responseBody.contentType()
}
override fun source(): BufferedSource {
return bufferedSource
}
private fun source(source: Source): Source {
return object : ForwardingSource(source) {
var totalBytesRead = 0L
override fun read(sink: Buffer, byteCount: Long): Long {
val bytesRead = super.read(sink, byteCount)
totalBytesRead += if (bytesRead != -1L) bytesRead else 0
val percent = if (bytesRead == -1L) 100f else totalBytesRead.toFloat() / responseBody.contentLength().toFloat() * 100
onAttachmentDownloadUpdate(percent.toInt())
return bytesRead
}
}
}
}
핵심은 source(source: Source) 부분으로, 내려받은 bytes 상태를 퍼센트로 변환하여 0~100의 수치로 콜백해 주는 역할을 한다.
3. 그다음 OkHttpClient를 만들어 주어야 한다.
private fun createOkHttpProgressClient(onAttachmentDownloadUpdate: (Int) -> Unit): OkHttpClient {
if (BuildConfig.DEBUG) {
val builder = OkHttpClient.Builder()
val interceptor = HttpLoggingInterceptor()
interceptor.level = HttpLoggingInterceptor.Level.BODY
builder.addInterceptor(interceptor)
builder.addInterceptor { chain ->
val originalResponse = chain.proceed(chain.request())
originalResponse.newBuilder()
.body(ProgressResponseBody(originalResponse.body(), onAttachmentDownloadUpdate))
.build()
}
return builder.build()
} else {
val builder = OkHttpClient.Builder()
return builder.build()
}
}
OkHttp에서 인터셉트를 함으로써 ProgressResponseBody의 로직을 거쳐 파일다운로드 진행상황을 받아올 수 있는 것임을 알 수 있다.
4. 네트워크 요청 로직을 완료한다.
private fun buildingRetrofit(onAttachmentDownloadUpdate: (Int) -> Unit){
val disposable = Retrofit.Builder()
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.baseUrl("https://www.서버 주소.kr/")
.client(createOkHttpProgressClient(onAttachmentDownloadUpdate))
.build()
.create(RetrofitService::class.java)
.requestFile()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
//TODO: 네트워크 완료 후 처리
}, {
//TODO: 네트워크 에러 처리
})
compositeDisposable.add(disposable)
}
실제 서비스 구현시에는, 좀더 세분화해서 처리하지만 포스팅을 위해 간략히 기재하였다.
이렇게 구현하면 buildingRetrofit을 호출할때 람다로 깔끔하게 UI 업데이트를 할 수 있다.
buildingRetrofit {
runOnUiThread {
progressBar.progress = it
}
}
반응형
'안드로이드 > 안드로이드 개발' 카테고리의 다른 글
안드로이드 레이아웃 이동 애니메이션 구현하기 (0) | 2019.06.07 |
---|---|
안드로이드(자바, 코틀린 포함) 문자열 언어 감지하기 (0) | 2019.05.26 |
안드로이드 원격 adb 설정하기 (1) | 2019.05.21 |
안드로이드 로그아웃 로직 (0) | 2019.05.03 |
안드로이드 개발 완료전 체크사항 정리 (0) | 2019.05.03 |
Comments