diff --git a/app/build.gradle b/app/build.gradle index 2c87053..cdb6f7d 100755 --- a/app/build.gradle +++ b/app/build.gradle @@ -5,14 +5,14 @@ apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' android { - compileSdkVersion 28 + compileSdkVersion 29 defaultConfig { applicationId "com.nekodev.paulina.sadowska.progressiveloadingdemo" minSdkVersion 17 - targetSdkVersion 28 + targetSdkVersion 29 versionCode 1 - versionName "1.0" - testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + versionName "2.0" + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } buildTypes { release { @@ -25,18 +25,28 @@ android { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" - implementation 'com.android.support:appcompat-v7:28.0.0' - implementation 'com.android.support.constraint:constraint-layout:1.1.3' + implementation 'androidx.appcompat:appcompat:1.1.0' + implementation 'androidx.constraintlayout:constraintlayout:1.1.3' - implementation 'io.reactivex.rxjava2:rxandroid:2.1.0' - implementation 'io.reactivex.rxjava2:rxjava:2.2.2' + // + implementation 'io.reactivex.rxjava2:rxandroid:2.1.1' + implementation 'io.reactivex.rxjava2:rxjava:2.2.6' implementation 'io.reactivex.rxjava2:rxkotlin:2.2.0' + // + // implementation 'com.squareup.picasso:picasso:2.71828' - implementation 'com.android.support:exifinterface:28.0.0' - //force picasso to use newer support lib version + implementation 'com.jakewharton.picasso:picasso2-okhttp3-downloader:1.0.2' + // - testImplementation 'junit:junit:4.12' - androidTestImplementation 'com.android.support.test:runner:1.0.2' - androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' + // + implementation 'com.facebook.stetho:stetho:1.5.1' + implementation 'com.facebook.stetho:stetho-okhttp3:1.5.1' // for OkHttp library + // + + // + testImplementation 'junit:junit:4.13' + androidTestImplementation 'androidx.test.ext:junit:1.1.1' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' + // } diff --git a/app/src/main/java/com/nekodev/paulina/sadowska/progressiveloadingdemo/ImageLoadingApplication.kt b/app/src/main/java/com/nekodev/paulina/sadowska/progressiveloadingdemo/ImageLoadingApplication.kt index 5c850d2..4c193bc 100644 --- a/app/src/main/java/com/nekodev/paulina/sadowska/progressiveloadingdemo/ImageLoadingApplication.kt +++ b/app/src/main/java/com/nekodev/paulina/sadowska/progressiveloadingdemo/ImageLoadingApplication.kt @@ -1,14 +1,35 @@ package com.nekodev.paulina.sadowska.progressiveloadingdemo import android.app.Application +import com.facebook.stetho.Stetho +import com.facebook.stetho.okhttp3.StethoInterceptor +import com.squareup.picasso.OkHttp3Downloader import com.squareup.picasso.Picasso import io.reactivex.plugins.RxJavaPlugins +import okhttp3.OkHttpClient +import java.util.concurrent.TimeUnit + class ImageLoadingApplication : Application() { override fun onCreate() { super.onCreate() + RxJavaPlugins.setErrorHandler(RxJavaErrorHandler()) - Picasso.get().isLoggingEnabled = true + + // open chrome://inspect/#devices on Chrome browse, then click on "inspect" link. + Stetho.initializeWithDefaults(this) + + val client = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS) + .addNetworkInterceptor(StethoInterceptor()) // add network interceptor + .build() + + val instance = Picasso.Builder(this) + .downloader(OkHttp3Downloader(client)) // custom downloader + .loggingEnabled(true) + .build() + + Picasso.setSingletonInstance(instance) } } diff --git a/app/src/main/java/com/nekodev/paulina/sadowska/progressiveloadingdemo/ImageViewModel.kt b/app/src/main/java/com/nekodev/paulina/sadowska/progressiveloadingdemo/ImageViewModel.kt index 2429ee5..411847e 100644 --- a/app/src/main/java/com/nekodev/paulina/sadowska/progressiveloadingdemo/ImageViewModel.kt +++ b/app/src/main/java/com/nekodev/paulina/sadowska/progressiveloadingdemo/ImageViewModel.kt @@ -1,6 +1,7 @@ package com.nekodev.paulina.sadowska.progressiveloadingdemo -import android.arch.lifecycle.MutableLiveData +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData import com.nekodev.paulina.sadowska.progressiveloadingdemo.fetcher.ImageFetcher import com.nekodev.paulina.sadowska.progressiveloadingdemo.fetcher.data.BitmapResult import com.nekodev.paulina.sadowska.progressiveloadingdemo.fetcher.data.BitmapWithQuality @@ -17,16 +18,28 @@ class ImageViewModel { private val disposable = CompositeDisposable() private val fetcher = ImageFetcher(Picasso.get()) - val bitmapResult = MutableLiveData() + private val _bitmapResult = MutableLiveData() + + val bitmapResult: LiveData + get() = _bitmapResult fun loadImages(qualities: List) { - bitmapResult.value = BitmapResult.loading() - disposable.add(fetcher.loadProgressively(BASE_IMAGE_URL, qualities) - .filter { getCurrentQuality() < it.quality } - .subscribeBy( - onNext = { applyImage(it) }, - onComplete = { postErrorIfNotSufficientQuality() } - )) + _bitmapResult.value = BitmapResult.loading() + + disposable.add( + fetcher.loadProgressively(BASE_IMAGE_URL, qualities) + .doOnSubscribe { resetImageView() } + .filter { getCurrentQuality() < it.quality } + .subscribeBy( + onNext = { applyImage(it) }, + onComplete = { + postErrorIfNotSufficientQuality() + } + )) + } + + private fun resetImageView() { + _bitmapResult.value = BitmapResult.loading() } private fun getCurrentQuality(): Int { @@ -34,12 +47,12 @@ class ImageViewModel { } private fun applyImage(bitmap: BitmapWithQuality) { - bitmapResult.value = BitmapResult.success(bitmap) + _bitmapResult.value = BitmapResult.success(bitmap) } - + private fun postErrorIfNotSufficientQuality() { if (getCurrentQuality() < 0) { - bitmapResult.value = BitmapResult.error() + _bitmapResult.value = BitmapResult.error() } } diff --git a/app/src/main/java/com/nekodev/paulina/sadowska/progressiveloadingdemo/MainActivity.kt b/app/src/main/java/com/nekodev/paulina/sadowska/progressiveloadingdemo/MainActivity.kt index 1a29265..792539d 100755 --- a/app/src/main/java/com/nekodev/paulina/sadowska/progressiveloadingdemo/MainActivity.kt +++ b/app/src/main/java/com/nekodev/paulina/sadowska/progressiveloadingdemo/MainActivity.kt @@ -1,10 +1,10 @@ package com.nekodev.paulina.sadowska.progressiveloadingdemo -import android.arch.lifecycle.Observer import android.graphics.Bitmap import android.os.Bundle -import android.support.v7.app.AppCompatActivity import android.view.View +import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.Observer import com.nekodev.paulina.sadowska.progressiveloadingdemo.fetcher.data.BitmapResult import com.nekodev.paulina.sadowska.progressiveloadingdemo.fetcher.data.ResponseState import kotlinx.android.synthetic.main.activity_main.* @@ -17,8 +17,8 @@ class MainActivity : AppCompatActivity() { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) - viewModel.bitmapResult.observe(this, Observer { it -> process(it) }) - viewModel.loadImages(listOf(3000, 10, 300)) + viewModel.bitmapResult.observe(this, Observer { process(it) }) + btn_load_image.setOnClickListener { viewModel.loadImages(listOf(3000, 10, 300)) } } private fun process(result: BitmapResult?) { @@ -26,6 +26,7 @@ class MainActivity : AppCompatActivity() { when (it.state) { ResponseState.LOADING -> { showProgress() + hideError() } ResponseState.ERROR -> { hideProgress() @@ -41,12 +42,17 @@ class MainActivity : AppCompatActivity() { } } + private fun hideError() { + errorText.visibility = View.GONE + } + private fun showImage(bitmap: Bitmap) { imageView.setImageBitmap(bitmap) } private fun showProgress() { loader.visibility = View.VISIBLE + imageView.setImageBitmap(null) } private fun hideProgress() { diff --git a/app/src/main/java/com/nekodev/paulina/sadowska/progressiveloadingdemo/fetcher/ImageFetcher.kt b/app/src/main/java/com/nekodev/paulina/sadowska/progressiveloadingdemo/fetcher/ImageFetcher.kt index 380c7ab..0b0a93a 100755 --- a/app/src/main/java/com/nekodev/paulina/sadowska/progressiveloadingdemo/fetcher/ImageFetcher.kt +++ b/app/src/main/java/com/nekodev/paulina/sadowska/progressiveloadingdemo/fetcher/ImageFetcher.kt @@ -10,6 +10,8 @@ import io.reactivex.Single */ class ImageFetcher(private val picasso: Picasso) { + private val pet = 237 + fun loadProgressively(baseUrl: String, qualities: List): Observable { return qualities .map { quality -> Pair(createUrl(baseUrl, quality), quality) } @@ -36,6 +38,6 @@ class ImageFetcher(private val picasso: Picasso) { .onErrorResumeNext(Observable.empty()) } - private fun createUrl(url: String, size: Int): String = "$url/$size/$size?image=0" //?image=0 added so image wont be random + private fun createUrl(url: String, size: Int): String = "$url/id/${pet}/$size/$size" } diff --git a/app/src/main/java/com/nekodev/paulina/sadowska/progressiveloadingdemo/fetcher/ImageFetcherSingleSubscribe.kt b/app/src/main/java/com/nekodev/paulina/sadowska/progressiveloadingdemo/fetcher/ImageFetcherSingleSubscribe.kt index 78f4d26..34b5a9f 100755 --- a/app/src/main/java/com/nekodev/paulina/sadowska/progressiveloadingdemo/fetcher/ImageFetcherSingleSubscribe.kt +++ b/app/src/main/java/com/nekodev/paulina/sadowska/progressiveloadingdemo/fetcher/ImageFetcherSingleSubscribe.kt @@ -1,6 +1,8 @@ package com.nekodev.paulina.sadowska.progressiveloadingdemo.fetcher import com.nekodev.paulina.sadowska.progressiveloadingdemo.fetcher.data.BitmapWithQuality +import com.squareup.picasso.MemoryPolicy +import com.squareup.picasso.NetworkPolicy import com.squareup.picasso.Picasso import com.squareup.picasso.Target import io.reactivex.SingleEmitter @@ -22,6 +24,8 @@ class ImageFetcherSingleSubscribe(private val picasso: Picasso, runningTargets.add(target) picasso.load(url) + .memoryPolicy(MemoryPolicy.NO_CACHE, MemoryPolicy.NO_STORE) // avoiding cache to force reload + .networkPolicy(NetworkPolicy.NO_CACHE, NetworkPolicy.NO_STORE) // avoiding cache to force reload .into(target) } diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 0eb7f65..7dcd7c4 100755 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -1,28 +1,55 @@ - +