Skip to content

Commit

Permalink
feat(mvi-presenter) Added view effects
Browse files Browse the repository at this point in the history
  • Loading branch information
PiotrBandurskiVA committed May 17, 2021
1 parent 42b96cf commit 9d85c07
Show file tree
Hide file tree
Showing 29 changed files with 271 additions and 99 deletions.
1 change: 1 addition & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ dependencies {
implementation deps.androidx.appcompat
implementation deps.androidx.core_ktx
implementation deps.androidx.constraint_layout
implementation deps.androidx.coordinator_layout
implementation deps.androidx.recycler_view
implementation deps.androidx.material
implementation deps.androidx.multidex
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,13 @@ import pl.valueadd.mvi.fragment.delegate.fragment.MviFragmentSaveInstanceStateDe
import pl.valueadd.mvi.presenter.BaseMviPresenter
import pl.valueadd.mvi.presenter.IBaseView

abstract class AbstractBaseMviFragment<V : IBaseView<VS, *>, VS : IBaseViewState, VI : IBaseView.IBaseIntent, P : BaseMviPresenter<VS, *, *, V>, Binding : ViewBinding> :
BaseMviFragment<V, VS, VI, P, Binding>() {
abstract class AbstractBaseMviFragment<
V : IBaseView<VS, *, *>,
VS : IBaseViewState,
VI : IBaseView.IBaseIntent,
VE : IBaseView.IBaseEffect,
P : BaseMviPresenter<VS, *, *, *, V>,
Binding : ViewBinding> : BaseMviFragment<V, VS, VI, VE, P, Binding>() {

protected val restoredViewState: VS?
get() = mviDelegate.restoredViewState
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import pl.valueadd.mvi.presenter.IBasePartialState
import pl.valueadd.mvi.presenter.IBaseView
import pl.valueadd.mvi.presenter.IBaseViewState

abstract class AbstractPresenter<VS : IBaseViewState, PS : IBasePartialState, VI : IBaseView.IBaseIntent, V : IBaseView<VS, VI>> :
BaseMviPresenter<VS, PS, VI, V>(AndroidSchedulers.mainThread()) {
abstract class AbstractPresenter<VS : IBaseViewState, PS : IBasePartialState, VI : IBaseView.IBaseIntent, VE : IBaseView.IBaseEffect, V : IBaseView<VS, VI, VE>> :
BaseMviPresenter<VS, PS, VI, VE, V>(AndroidSchedulers.mainThread()) {

override fun onError(throwable: Throwable) {
super.onError(throwable)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import pl.valueadd.mvi.presenter.IBaseView
import javax.inject.Inject

class AboutFragment :
AbstractBaseMviFragment<AboutView, AboutViewState, IBaseView.IBaseIntent, AboutPresenter, FragmentAboutBinding>(),
AbstractBaseMviFragment<AboutView, AboutViewState, IBaseView.IBaseIntent, IBaseView.IBaseEffect, AboutPresenter, FragmentAboutBinding>(),
AboutView {

override val bindingInflater: FragmentBindingInflater<FragmentAboutBinding>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import pl.valueadd.mvi.presenter.IBaseView
import javax.inject.Inject

class AboutPresenter @Inject constructor() :
AbstractPresenter<AboutViewState, AboutViewState.PartialState, IBaseView.IBaseIntent, AboutView>() {
AbstractPresenter<AboutViewState, AboutViewState.PartialState, IBaseView.IBaseIntent, IBaseView.IBaseEffect, AboutView>() {

override fun reduce(
previousState: AboutViewState,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ package pl.valueadd.mvi.example.presentation.main.about
import pl.valueadd.mvi.presenter.IBaseView

interface AboutView :
IBaseView<AboutViewState, IBaseView.IBaseIntent>
IBaseView<AboutViewState, IBaseView.IBaseIntent, IBaseView.IBaseEffect>
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@ import pl.valueadd.mvi.example.presentation.base.AbstractBaseMviFragment
import pl.valueadd.mvi.example.utility.extension.applyTextChanges
import pl.valueadd.mvi.fragment.base.FragmentBindingInflater
import pl.valueadd.mvi.fragment.delegate.destroyview.DestroyViewIntentDelegate
import pl.valueadd.mvi.presenter.IBaseView
import javax.inject.Inject

class AccountFragment :
AbstractBaseMviFragment<AccountView, AccountViewState, AccountView.Intent, AccountPresenter, FragmentAccountBinding>(),
AbstractBaseMviFragment<AccountView, AccountViewState, AccountView.Intent, IBaseView.IBaseEffect, AccountPresenter, FragmentAccountBinding>(),
AccountView {

@Inject
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ package pl.valueadd.mvi.example.presentation.main.account

import io.reactivex.Observable
import pl.valueadd.mvi.example.presentation.base.AbstractPresenter
import pl.valueadd.mvi.presenter.IBaseView
import javax.inject.Inject

class AccountPresenter @Inject constructor() :
AbstractPresenter<AccountViewState, AccountViewState.PartialState, AccountView.Intent, AccountView>() {
AbstractPresenter<AccountViewState, AccountViewState.PartialState, AccountView.Intent, IBaseView.IBaseEffect, AccountView>() {

override fun reduce(
previousState: AccountViewState,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package pl.valueadd.mvi.example.presentation.main.account
import pl.valueadd.mvi.presenter.IBaseView

interface AccountView :
IBaseView<AccountViewState, AccountView.Intent> {
IBaseView<AccountViewState, AccountView.Intent, IBaseView.IBaseEffect> {

sealed class Intent : IBaseView.IBaseIntent {
data class OnDestroyView(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package pl.valueadd.mvi.example.presentation.main.first
import android.os.Bundle
import android.view.View
import androidx.navigation.fragment.findNavController
import com.google.android.material.snackbar.Snackbar
import io.reactivex.Observable
import pl.valueadd.mvi.example.R
import pl.valueadd.mvi.example.databinding.FragmentFirstBinding
Expand All @@ -13,7 +14,7 @@ import pl.valueadd.mvi.fragment.base.FragmentBindingInflater
import javax.inject.Inject

class FirstFragment :
AbstractBaseMviFragment<FirstView, FirstViewState, FirstView.Intent, FirstPresenter, FragmentFirstBinding>(),
AbstractBaseMviFragment<FirstView, FirstViewState, FirstView.Intent, FirstView.Effect, FirstPresenter, FragmentFirstBinding>(),
FirstView {

@Inject
Expand All @@ -34,15 +35,19 @@ class FirstFragment :
return restoredViewState ?: FirstViewState()
}

override fun navigateToAboutView() {
findNavController().navigate(R.id.action_firstFragment_to_aboutFragment)
}

override fun render(state: FirstViewState): Unit = with(requireBinding) {
counterText.text = state.count.toString()
resultValueText.text = state.value
}

override fun handleViewEffect(effect: FirstView.Effect) {
when (effect) {
is FirstView.Effect.ShowMessage -> Snackbar
.make(requireBinding.firstFragmentLinearLayout, effect.message, Snackbar.LENGTH_SHORT)
.show()
}
}

override fun provideViewIntents(): List<Observable<FirstView.Intent>> = listOf(
increaseCount(),
decreaseCount(),
Expand All @@ -69,4 +74,8 @@ class FirstFragment :
.throttleClicks()
.onSuccess(disposables, { navigateToAboutView() })
}

private fun navigateToAboutView() {
findNavController().navigate(R.id.action_firstFragment_to_aboutFragment)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import pl.valueadd.mvi.example.presentation.base.AbstractPresenter
import java.util.concurrent.TimeUnit
import javax.inject.Inject

class FirstPresenter @Inject constructor() : AbstractPresenter<FirstViewState, FirstViewState.PartialState, FirstView.Intent, FirstView>() {
class FirstPresenter @Inject constructor() : AbstractPresenter<FirstViewState, FirstViewState.PartialState, FirstView.Intent, FirstView.Effect, FirstView>() {
companion object {
private const val PROCESSING_DELAY = 5L
}
Expand Down Expand Up @@ -45,7 +45,10 @@ class FirstPresenter @Inject constructor() : AbstractPresenter<FirstViewState, F
private fun handleProcessDataIntent(): Observable<out FirstViewState.PartialState> {
return Observable
.just(currentState.count)
.doOnNext { Log.d("MVI-FirstPresenter", "processData") }
.doOnNext {
Log.d("MVI-FirstPresenter", "processData")
pushViewEffect(FirstView.Effect.ShowMessage("Started processing"))
}
.delay(PROCESSING_DELAY, TimeUnit.SECONDS)
.map { count -> FirstViewState.PartialState.ProcessDataSuccess("$count%") }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ package pl.valueadd.mvi.example.presentation.main.first
import pl.valueadd.mvi.presenter.IBaseView

interface FirstView :
IBaseView<FirstViewState, FirstView.Intent> {

fun navigateToAboutView()
IBaseView<FirstViewState, FirstView.Intent, FirstView.Effect> {

sealed class Intent : IBaseView.IBaseIntent {
object IncreaseCount : Intent()
object DecreaseCount : Intent()
object ProcessData : Intent()
}

sealed class Effect : IBaseView.IBaseEffect {
data class ShowMessage(val message: String) : Effect()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import pl.valueadd.mvi.fragment.base.FragmentBindingInflater
import pl.valueadd.mvi.presenter.IBaseView
import javax.inject.Inject

class SecondFragment : AbstractBaseMviFragment<SecondView, SecondViewState, IBaseView.IBaseIntent, SecondPresenter, FragmentSecondBinding>(),
class SecondFragment : AbstractBaseMviFragment<SecondView, SecondViewState, IBaseView.IBaseIntent, IBaseView.IBaseEffect, SecondPresenter, FragmentSecondBinding>(),
SecondView {

@Inject
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import pl.valueadd.mvi.presenter.IBaseView
import javax.inject.Inject

class SecondPresenter
@Inject constructor() : AbstractPresenter<SecondViewState, SecondViewState.PartialState, IBaseView.IBaseIntent, SecondView>() {
@Inject constructor() : AbstractPresenter<SecondViewState, SecondViewState.PartialState, IBaseView.IBaseIntent, IBaseView.IBaseEffect, SecondView>() {

override fun reduce(
previousState: SecondViewState,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ package pl.valueadd.mvi.example.presentation.main.second
import pl.valueadd.mvi.presenter.IBaseView

interface SecondView :
IBaseView<SecondViewState, IBaseView.IBaseIntent>
IBaseView<SecondViewState, IBaseView.IBaseIntent, IBaseView.IBaseEffect>
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import pl.valueadd.mvi.presenter.IBaseView
import javax.inject.Inject

class ThirdFragment :
AbstractBaseMviFragment<ThirdView, ThirdViewState, IBaseView.IBaseIntent, ThirdPresenter, FragmentThirdBinding>(),
AbstractBaseMviFragment<ThirdView, ThirdViewState, IBaseView.IBaseIntent, IBaseView.IBaseEffect, ThirdPresenter, FragmentThirdBinding>(),
ThirdView {

@Inject
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import pl.valueadd.mvi.presenter.IBaseView
import javax.inject.Inject

class ThirdPresenter @Inject constructor() :
AbstractPresenter<ThirdViewState, ThirdViewState.PartialState, IBaseView.IBaseIntent, ThirdView>() {
AbstractPresenter<ThirdViewState, ThirdViewState.PartialState, IBaseView.IBaseIntent, IBaseView.IBaseEffect, ThirdView>() {

override fun reduce(
previousState: ThirdViewState,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ package pl.valueadd.mvi.example.presentation.main.third
import pl.valueadd.mvi.presenter.IBaseView

interface ThirdView :
IBaseView<ThirdViewState, IBaseView.IBaseIntent>
IBaseView<ThirdViewState, IBaseView.IBaseIntent, IBaseView.IBaseEffect>
112 changes: 60 additions & 52 deletions app/src/main/res/layout/fragment_first.xml
Original file line number Diff line number Diff line change
@@ -1,85 +1,93 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/coordinatorLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="@string/first_title" />
android:layout_above="@+id/bottomNavigation">

<LinearLayout
android:id="@+id/firstFragmentLinearLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="horizontal">
android:orientation="vertical">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="@string/first_result" />
android:text="@string/first_title" />

<TextView
android:id="@+id/resultValueText"
android:layout_width="wrap_content"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center" />
android:gravity="center"
android:orientation="horizontal">

</LinearLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="@string/first_result" />

<com.google.android.material.button.MaterialButton
android:id="@+id/aboutButton"
style="@style/AppTheme.Widget.Button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/margin_big"
android:text="@string/about_title" />
<TextView
android:id="@+id/resultValueText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center" />

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/margin_big"
android:layout_marginBottom="@dimen/margin_big"
android:gravity="center"
android:orientation="horizontal">
</LinearLayout>

<com.google.android.material.button.MaterialButton
android:id="@+id/addButton"
android:id="@+id/aboutButton"
style="@style/AppTheme.Widget.Button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/first_add" />
android:layout_marginTop="@dimen/margin_big"
android:text="@string/about_title" />

<TextView
android:id="@+id/counterText"
android:layout_width="wrap_content"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/margin_big"
android:layout_marginEnd="@dimen/margin_big"
android:textAppearance="@style/TextAppearance.AppCompat.Headline"
tools:text="15" />
android:layout_marginTop="@dimen/margin_big"
android:layout_marginBottom="@dimen/margin_big"
android:gravity="center"
android:orientation="horizontal">

<com.google.android.material.button.MaterialButton
android:id="@+id/addButton"
style="@style/AppTheme.Widget.Button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/first_add" />

<TextView
android:id="@+id/counterText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/margin_big"
android:layout_marginEnd="@dimen/margin_big"
android:textAppearance="@style/TextAppearance.AppCompat.Headline"
tools:text="15" />

<com.google.android.material.button.MaterialButton
android:id="@+id/removeButton"
style="@style/AppTheme.Widget.Button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/first_remove" />

</LinearLayout>

<com.google.android.material.button.MaterialButton
android:id="@+id/removeButton"
android:id="@+id/processButton"
style="@style/AppTheme.Widget.Button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/first_remove" />
android:layout_marginTop="@dimen/margin_big"
android:text="@string/about_process" />

</LinearLayout>

<com.google.android.material.button.MaterialButton
android:id="@+id/processButton"
style="@style/AppTheme.Widget.Button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/margin_big"
android:text="@string/about_process" />

</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
8 changes: 8 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,12 @@ allprojects {
apply from: "$rootDir/scripts/detekt.gradle"
apply from: "$rootDir/scripts/ktlint.gradle"
apply from: "$rootDir/scripts/pmd.gradle"

tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
kotlinOptions {
jvmTarget = "1.8"
languageVersion = "1.3"
useIR = findProperty("kotlin.ir.enabled")?.toBoolean() == true
}
}
}
Loading

0 comments on commit 9d85c07

Please sign in to comment.