Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,9 @@ dependencies {
implementation deps.mvp.mosby_view_state
implementation deps.mvp.mosby_queuing

// Reactivex
implementation deps.rx.binding
// Coroutines
implementation deps.coroutines.core
implementation deps.coroutines.android

// Permissions
implementation deps.permissions.no
Expand Down Expand Up @@ -139,6 +140,7 @@ dependencies {
androidTestImplementation deps.test.dexmaker_mockito
androidTestImplementation deps.test.androidx_runner
androidTestImplementation deps.test.androidx_rules

}

// Final plugins
Expand Down
Original file line number Diff line number Diff line change
@@ -1,27 +1,20 @@
package pl.valueadd.restcountries.presentation.base

import com.hannesdorfmann.mosby3.mvp.MvpQueuingBasePresenter
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.disposables.Disposable
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.MainScope
import pl.valueadd.restcountries.utility.coroutines.cancelSafe

abstract class BasePresenter<V : BaseView> : MvpQueuingBasePresenter<V>() {

/**
* Contains disposable subscription of streams.
*/
protected val disposables: CompositeDisposable
by lazy { CompositeDisposable() }
protected val scope by lazy { MainScope() }

/**
* Add subscription to composite.
*/
protected fun addDisposable(disposable: Disposable): Boolean =
disposables.add(disposable)
fun exceptionHandler(method: (Throwable) -> Unit): CoroutineExceptionHandler {
return CoroutineExceptionHandler { _, throwable -> method(throwable) }
}

/**
* Clear all subscriptions.
*/
fun clearDisposables() {
disposables.clear()
override fun detachView() {
scope.cancelSafe()
super.detachView()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import androidx.annotation.IdRes
import androidx.annotation.LayoutRes
import androidx.core.content.ContextCompat
import com.hannesdorfmann.mosby3.mvp.MvpActivity
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.disposables.Disposable
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.MainScope
import me.yokeyword.fragmentation.ExtraTransaction
import me.yokeyword.fragmentation.ISupportFragment
import me.yokeyword.fragmentation.SupportActivityDelegate
Expand All @@ -21,6 +21,7 @@ import pl.valueadd.restcountries.R
import pl.valueadd.restcountries.presentation.base.BasePresenter
import pl.valueadd.restcountries.presentation.base.BaseView
import pl.valueadd.restcountries.presentation.base.fragment.base.IBaseFragment
import pl.valueadd.restcountries.utility.coroutines.cancelSafe
import pl.valueadd.restcountries.utility.dependencyinjection.DependencyUtil
import pl.valueadd.restcountries.utility.view.snackbar.SnackbarUtil
import javax.inject.Inject
Expand All @@ -30,7 +31,8 @@ abstract class BaseMVPActivity<V : BaseView, P : BasePresenter<V>>(
) :
MvpActivity<V, P>(),
IBaseActivity,
BaseView {
BaseView,
CoroutineScope by MainScope() {

private val delegate: SupportActivityDelegate
by lazy { SupportActivityDelegate(this) }
Expand All @@ -45,25 +47,6 @@ abstract class BaseMVPActivity<V : BaseView, P : BasePresenter<V>>(
protected open val menuLayout: Int
get() = R.menu.main_menu

/**
* Contains disposable subscriptions of streams.
*/
protected val disposables: CompositeDisposable
by lazy { CompositeDisposable() }

/**
* Add subscription to composite.
*/
protected fun addDisposable(disposable: Disposable): Boolean =
disposables.add(disposable)

/**
* Clear all subscriptions.
*/
protected fun clearDisposables() {
disposables.clear()
}

protected fun showError(error: String, view: View) =
snackBarUtil.showMessage(view, error, ContextCompat.getColor(this, R.color.red))

Expand Down Expand Up @@ -98,7 +81,7 @@ abstract class BaseMVPActivity<V : BaseView, P : BasePresenter<V>>(
}

override fun onDestroy() {
clearDisposables()
cancelSafe()

delegate.onDestroy()
super.onDestroy()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ import androidx.annotation.LayoutRes
import androidx.fragment.app.Fragment
import pl.valueadd.restcountries.presentation.base.activity.IBaseActivity
import pl.valueadd.restcountries.utility.dependencyinjection.DependencyUtil
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.disposables.Disposable
import me.yokeyword.fragmentation.ExtraTransaction
import me.yokeyword.fragmentation.ISupportFragment
import me.yokeyword.fragmentation.SupportFragmentDelegate
Expand All @@ -23,25 +21,6 @@ abstract class BaseFragment(@LayoutRes protected val layoutId: Int) : Fragment()
private val fragmentDelegate: SupportFragmentDelegate
by lazy { SupportFragmentDelegate(this) }

/**
* Contains disposable subscriptions of streams.
*/
protected val disposables: CompositeDisposable
by lazy { CompositeDisposable() }

/**
* Add subscription to composite.
*/
protected fun addDisposable(disposable: Disposable): Boolean =
disposables.add(disposable)

/**
* Clear all subscriptions.
*/
protected fun clearDisposables() {
disposables.clear()
}

/* Life cycle */

override fun onCreateView(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,18 @@ import pl.valueadd.restcountries.utility.view.snackbar.SnackbarUtil
import com.hannesdorfmann.mosby3.mvp.delegate.FragmentMvpDelegate
import com.hannesdorfmann.mosby3.mvp.delegate.FragmentMvpDelegateImpl
import com.hannesdorfmann.mosby3.mvp.delegate.MvpDelegateCallback
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.MainScope
import pl.valueadd.restcountries.presentation.base.BasePresenter
import pl.valueadd.restcountries.presentation.base.BaseView
import pl.valueadd.restcountries.utility.coroutines.cancelSafe
import javax.inject.Inject

abstract class BaseMVPFragment<V : BaseView, P : BasePresenter<V>>(@LayoutRes layoutId: Int) :
BaseFragment(layoutId),
MvpDelegateCallback<V, P>,
BaseView {
BaseView,
CoroutineScope by MainScope() {

@Inject
lateinit var snackBarUtil: SnackbarUtil
Expand Down Expand Up @@ -105,8 +109,7 @@ abstract class BaseMVPFragment<V : BaseView, P : BasePresenter<V>>(@LayoutRes la
}

override fun onDetach() {
presenter.clearDisposables()
clearDisposables()
cancelSafe()

super.onDetach()
mvpDelegate.onDestroy()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,9 @@ import pl.valueadd.restcountries.domain.model.country.CountryModel
import pl.valueadd.restcountries.presentation.base.fragment.viewstate.back.BackMVPViewStateFragment
import pl.valueadd.restcountries.utility.common.merge
import pl.valueadd.restcountries.utility.image.loadSVGImage
import pl.valueadd.restcountries.utility.reactivex.onSuccess
import pl.valueadd.restcountries.utility.reactivex.throttleClicks
import pl.valueadd.restcountries.utility.view.getChildAtOrNull
import pl.valueadd.restcountries.utility.view.setVisible
import pl.valueadd.restcountries.utility.view.throttleClicks
import pl.valueadd.restcountries.utility.view.toolbar.CollapsingToolbarState
import pl.valueadd.restcountries.utility.view.toolbar.onCollapsingToolbarStateChanged
import pl.valueadd.restcountries.view.chip.BorderChip
Expand Down Expand Up @@ -89,10 +88,9 @@ class CountryDetailsFragment : BackMVPViewStateFragment<CountryDetailsView, Coun

for (model in models) {
val chip = createBorderChip(model)

chip.throttleClicks()
.onSuccess(disposables, { presenter.onBorderItemClick(model.id) })

chip.throttleClicks(this) {
presenter.onBorderItemClick(model.id)
}
bordersChipGroup.addView(chip)
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package pl.valueadd.restcountries.presentation.main.countries.details

import io.reactivex.rxkotlin.addTo
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import pl.valueadd.restcountries.domain.manager.CountryDomainManager
import pl.valueadd.restcountries.domain.manager.ExceptionDomainManager
import pl.valueadd.restcountries.domain.model.country.CountryFlatModel
import pl.valueadd.restcountries.domain.model.country.CountryModel
import pl.valueadd.restcountries.presentation.base.BasePresenter
import pl.valueadd.restcountries.utility.reactivex.observeOnMain
import timber.log.Timber
import javax.inject.Inject

Expand All @@ -32,14 +32,13 @@ class CountryDetailsPresenter @Inject constructor(
}

private fun observeCountry(countryId: String) {
countryManager
.observeCountry(countryId)
.observeOnMain()
.subscribe(
::onObserveCountrySuccess,
::onObserveCountryFailed
)
.addTo(disposables)
scope.launch(exceptionHandler(::onObserveCountryFailed)) {
countryManager
.observeCountry(countryId)
.collectLatest {
onObserveCountrySuccess(it)
}
}
}

private fun onObserveCountrySuccess(model: CountryModel) = onceViewAttached { view ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,8 @@ import pl.valueadd.restcountries.presentation.main.countries.list.item.ClickCoun
import pl.valueadd.restcountries.presentation.main.countries.list.item.CountryHeaderAdapter
import pl.valueadd.restcountries.presentation.main.root.RootFragment
import pl.valueadd.restcountries.utility.context.createBottomSheetDialog
import pl.valueadd.restcountries.utility.reactivex.onSuccess
import pl.valueadd.restcountries.utility.reactivex.throttleClicks
import pl.valueadd.restcountries.utility.view.applyAligmentToTheRight
import pl.valueadd.restcountries.utility.view.throttleClicks
import pl.valueadd.restcountries.view.decorator.CountryItemDecoration
import javax.inject.Inject

Expand Down Expand Up @@ -136,12 +135,10 @@ class CountryListFragment : BackMVPViewStateFragment<CountryListView, CountryLis
}

private fun initializeChipGroup() = bordersChipGroup.run {

sortByNameChip
.throttleClicks()
.onSuccess(disposables, {
.throttleClicks(this@CountryListFragment) {
presenter.onSortByNameViewClick()
})
}
}

override fun initializeToolbarNavigation(toolbar: Toolbar) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package pl.valueadd.restcountries.presentation.main.countries.list

import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.rxkotlin.addTo
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.launch
import org.apache.commons.lang3.StringUtils.EMPTY
import pl.valueadd.restcountries.domain.manager.CountryDomainManager
import pl.valueadd.restcountries.domain.manager.ExceptionDomainManager
Expand All @@ -11,9 +13,7 @@ import pl.valueadd.restcountries.domain.model.helper.Filter
import pl.valueadd.restcountries.presentation.base.BasePresenter
import pl.valueadd.restcountries.presentation.main.countries.list.item.ClickCountryItemEventHook
import pl.valueadd.restcountries.presentation.main.countries.list.item.CountryItem
import pl.valueadd.restcountries.utility.reactivex.observeOnMain
import timber.log.Timber
import java.util.concurrent.TimeUnit
import javax.inject.Inject

class CountryListPresenter
Expand All @@ -37,7 +37,7 @@ class CountryListPresenter

var isAscending: Boolean = true

private var countriesDisposable: Disposable? = null
private var observeCountriesJob: Job? = null

override fun onCountryItemClick(model: CountryModel) = onceViewAttached {
it.navigateToCountryDetailsView(model.id)
Expand All @@ -59,9 +59,7 @@ class CountryListPresenter
Filters.NameDsc
}

countriesDisposable?.let {
disposables.remove(it)
}
observeCountriesJob?.cancel()

observeCountries(query, true, filter)
}
Expand All @@ -71,14 +69,12 @@ class CountryListPresenter
}

private fun downloadAllCountries() {
countryManager
.downloadAllCountries()
.observeOnMain()
.subscribe(
::onDownloadAllExamplesSuccess,
::onDownloadAllExamplesFailed
)
.addTo(disposables)
scope.launch(Dispatchers.Default + exceptionHandler(::onDownloadAllExamplesFailed)) {
countryManager.downloadAllCountries()
launch(Dispatchers.Main) {
onDownloadAllExamplesSuccess()
}
}
}

private fun onDownloadAllExamplesSuccess() {
Expand All @@ -96,19 +92,15 @@ class CountryListPresenter
}

private fun observeCountries(query: String = EMPTY, isDelayed: Boolean = false, filter: Filter<CountryModel> = Filters.NameAsc) {
countriesDisposable = countryManager
.observeCountries(query, filter)
.apply {
if (isDelayed) {
debounce(DELAY, TimeUnit.MILLISECONDS, AndroidSchedulers.mainThread())
}
observeCountriesJob = scope.launch(exceptionHandler(::onObserveAllCountriesFailed)) {
var countriesFlow = countryManager.observeCountries(query, filter)
if (isDelayed) {
countriesFlow = countriesFlow.debounce(DELAY)
}
.observeOnMain()
.subscribe(
::onObserveAllCountriesSuccess,
::onObserveAllCountriesFailed
)
.addTo(disposables)
countriesFlow.collectLatest {
onObserveAllCountriesSuccess(it)
}
}
}

private fun onObserveAllCountriesSuccess(list: List<CountryModel>) = onceViewAttached { view ->
Expand Down
Loading