Skip to content

Commit

Permalink
finish view state handling with MVI quirks
Browse files Browse the repository at this point in the history
  • Loading branch information
FunkyMuse committed Nov 22, 2021
1 parent cbe5b13 commit b1817a7
Show file tree
Hide file tree
Showing 24 changed files with 637 additions and 145 deletions.
2 changes: 2 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ dependencies {
implementation project(path: ':animations')
implementation project(path: ':view')
implementation project(path: ':collections')
implementation project(path: ':lifecycle')
implementation project(path: ':fragment')


testImplementation "junit:junit:$junitVersion"
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainAbstractActivity" android:exported="true">
<activity android:name=".nav.NavActivity" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<action android:name="android.intent.action.VIEW" />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.crazylegend.setofusefulkotlinextensions


import android.annotation.SuppressLint
import android.os.Bundle
import android.view.Menu
import androidx.activity.viewModels
Expand All @@ -9,10 +10,8 @@ import androidx.core.os.bundleOf
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.RecyclerView
import com.crazylegend.animations.transition.utils.fadeRecyclerTransition
import com.crazylegend.animations.transition.stagger
import com.crazylegend.context.getColorCompat
import com.crazylegend.context.isGestureNavigationEnabled
import com.crazylegend.context.shortToast
import com.crazylegend.coroutines.textChanges
import com.crazylegend.customviews.AppRater
import com.crazylegend.customviews.autoStart.AutoStartHelper
Expand All @@ -24,9 +23,13 @@ import com.crazylegend.kotlinextensions.log.debug
import com.crazylegend.kotlinextensions.misc.RunCodeEveryXLaunch
import com.crazylegend.kotlinextensions.views.asSearchView
import com.crazylegend.kotlinextensions.views.setQueryAndExpand
import com.crazylegend.recyclerview.*
import com.crazylegend.lifecycle.repeatingJobOnStarted
import com.crazylegend.recyclerview.RecyclerSwipeItemHandler
import com.crazylegend.recyclerview.addSwipe
import com.crazylegend.recyclerview.clickListeners.forItemClickListener
import com.crazylegend.retrofit.retrofitResult.*
import com.crazylegend.recyclerview.generateRecycler
import com.crazylegend.recyclerview.hideOnScroll
import com.crazylegend.retrofit.retrofitResult.RetrofitResult
import com.crazylegend.retrofit.throwables.NoConnectionException
import com.crazylegend.setofusefulkotlinextensions.adapter.TestModel
import com.crazylegend.setofusefulkotlinextensions.adapter.TestPlaceHolderAdapter
Expand Down Expand Up @@ -55,8 +58,8 @@ class MainAbstractActivity : AppCompatActivity() {

private val exampleGeneratedAdapter by lazy {
generateRecycler<TestModel, TestViewHolderShimmer, CustomizableCardViewBinding>(
::TestViewHolderShimmer,
CustomizableCardViewBinding::inflate
::TestViewHolderShimmer,
CustomizableCardViewBinding::inflate
) { item, holder, _, _ ->
holder.bind(item)
}
Expand All @@ -66,6 +69,8 @@ class MainAbstractActivity : AppCompatActivity() {
InternetDetector(this)
}



private val activityMainBinding by viewBinding(ActivityMainBinding::inflate)
private var savedItemAnimator: RecyclerView.ItemAnimator? = null

Expand All @@ -79,12 +84,14 @@ class MainAbstractActivity : AppCompatActivity() {
savedInstanceState?.getString("query", null)?.let { savedQuery = it }

activityMainBinding.test.setOnClickListenerCooldown {
testAVM.getposts()
testAVM.getPosts()
}
lifecycleScope.launchWhenResumed {
testAVM.posts.collect {
activityMainBinding.recycler.adapter = generatedAdapter

repeatingJobOnStarted {
/* testAVM.posts.collect {
updateUI(it)
}
}*/
}

RunCodeEveryXLaunch.runCode(this, 2) {
Expand Down Expand Up @@ -115,11 +122,11 @@ class MainAbstractActivity : AppCompatActivity() {
}

AutoStartHelper.checkAutoStart(
this, dialogBundle = bundleOf(
this, dialogBundle = bundleOf(
Pair(ConfirmationDialogAutoStart.CANCEL_TEXT, "Dismiss"),
Pair(ConfirmationDialogAutoStart.CONFIRM_TEXT, "Allow"),
Pair(ConfirmationDialogAutoStart.DO_NOT_SHOW_AGAIN_VISIBILITY, true)
)
)
)

if (isGestureNavigationEnabled()) {
Expand All @@ -135,44 +142,31 @@ class MainAbstractActivity : AppCompatActivity() {
}

private fun updateUI(retrofitResult: RetrofitResult<List<TestModel>>) {
/* retrofitResult.asMVIResult(testAVM.resultMVI) { getAsSuccess.isNotNullOrEmpty }
testAVM.resultMVI
.result
.onError { retryOnInternetAvailable(it) }
.onSuccess {
activityMainBinding.progressBar.gone()
generatedAdapter.submitList(it)
}*/

retrofitResult
.onSuccess {
activityMainBinding.recycler.stagger()
activityMainBinding.recycler.replaceAdapterWith(
generatedAdapter,
fade
) { itemAnimator ->
savedItemAnimator = itemAnimator
}
generatedAdapter.submitList(it)
val wrappedList = it.toMutableList()
activityMainBinding.recycler.addDrag(generatedAdapter, wrappedList)
}
.onLoading {
activityMainBinding.recycler.adapter = testPlaceHolderAdapter
}
.onError {
if (it is NoConnectionException) {
lifecycleScope.launch {
internetDetector.state.collect {
if (it) {
testAVM.getposts()
}
}

}

private fun retryOnInternetAvailable(throwable: Throwable) {
if (throwable is NoConnectionException) {
lifecycleScope.launch {
internetDetector.state.collect { hasConnection ->
if (hasConnection) {
testAVM.getPosts()
}
}

activityMainBinding.recycler.adapter = generatedAdapter
generatedAdapter.submitList(emptyList())
}
.onApiError { errorBody, _ ->
shortToast(testAVM.handleApiError(errorBody) ?: "Error")
activityMainBinding.recycler.adapter = generatedAdapter
generatedAdapter.submitList(emptyList())
}
}
}

@SuppressLint("MissingSuperCall")
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
savedQuery?.let { outState.putString("query", it) }
Expand All @@ -188,11 +182,11 @@ class MainAbstractActivity : AppCompatActivity() {
searchItem.asSearchView()?.apply {
queryHint = "Search by title"
getEditTextSearchView?.textChanges(skipInitialValue = true, debounce = 350L)
?.map { it?.toString() }
?.onEach {
debug("TEXT $it")
savedQuery = it
}?.launchIn(lifecycleScope)
?.map { it?.toString() }
?.onEach {
debug("TEXT $it")
savedQuery = it
}?.launchIn(lifecycleScope)
}

return super.onCreateOptionsMenu(menu)
Expand All @@ -206,3 +200,4 @@ class MainAbstractActivity : AppCompatActivity() {




Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,20 @@ import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.viewModelScope
import com.crazylegend.common.randomUUIDstring
import com.crazylegend.kotlinextensions.viewmodel.context
import com.crazylegend.retrofit.adapter.RetrofitResultAdapterFactory
import com.crazylegend.retrofit.interceptors.ConnectivityInterceptor
import com.crazylegend.retrofit.randomPhotoIndex
import com.crazylegend.retrofit.retrofitResult.RetrofitResult
import com.crazylegend.retrofit.viewstate.ViewState
import com.crazylegend.retrofit.viewstate.ViewStateContract
import com.crazylegend.retrofit.viewstate.asViewStatePayloadWithEvents
import com.crazylegend.setofusefulkotlinextensions.adapter.TestModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
import okhttp3.ResponseBody
import okhttp3.OkHttpClient
import retrofit2.Retrofit
import retrofit2.converter.moshi.MoshiConverterFactory
import retrofit2.create
Expand All @@ -25,33 +32,47 @@ import retrofit2.create
* Template created by Hristijan to live long and prosper.
*/

class TestAVM(application: Application, private val savedStateHandle: SavedStateHandle) : AndroidViewModel(application) {
class TestAVM(application: Application, val savedStateHandle: SavedStateHandle) : AndroidViewModel(application),
ViewStateContract<List<TestModel>> by ViewState() {

companion object {
private const val errorStateKey = "errorJSONKey"
}
val posts: StateFlow<RetrofitResult<List<TestModel>>> = data

private val postsData = MutableStateFlow<RetrofitResult<List<TestModel>>>(RetrofitResult.Idle)
val posts = postsData.asStateFlow()
fun getPosts() {
viewModelScope.launch {
setLoading()
delay(2000)
fetchPosts()
}
}

fun getposts() {
postsData.value = RetrofitResult.Loading
fun getRandomPosts() {
viewModelScope.launch {
postsData.value = retrofit.getPosts()
setLoading()
delay(2000)
RetrofitResult.Success(listOf(
TestModel(randomUUIDstring, randomPhotoIndex, randomUUIDstring, randomPhotoIndex),
TestModel(randomUUIDstring, randomPhotoIndex, randomUUIDstring, randomPhotoIndex),
TestModel(randomUUIDstring, randomPhotoIndex, randomUUIDstring, randomPhotoIndex),
TestModel(randomUUIDstring, randomPhotoIndex, randomUUIDstring, randomPhotoIndex),
)).asViewStatePayloadWithEvents(this@TestAVM)
}
}

fun handleApiError(errorBody: ResponseBody?): String? {
val json = errorBody?.string()
if (json.isNullOrEmpty()) return savedStateHandle.get<String>(errorStateKey)
savedStateHandle[errorStateKey] = json
private suspend fun setLoading() {
RetrofitResult.Loading.asViewStatePayloadWithEvents(this)
}

return savedStateHandle.get<String>(errorStateKey)
private suspend fun fetchPosts() {
retrofit.getPosts().asViewStatePayloadWithEvents(this)
}


private val retrofit by lazy {
with(Retrofit.Builder()){
with(Retrofit.Builder()) {
client(with(OkHttpClient.Builder()) {
addInterceptor(ConnectivityInterceptor(context))
build()
})
baseUrl(TestApi.API)
addCallAdapterFactory(RetrofitResultAdapterFactory())
addConverterFactory(MoshiConverterFactory.create())
Expand All @@ -60,10 +81,8 @@ class TestAVM(application: Application, private val savedStateHandle: SavedState
}

init {
getposts()
getPosts()
}

}



Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,9 @@ class NavActivity : AppCompatActivity() {
private val currentNavController get() = binding.fragmentContainer.getFragment<NavHostFragment>().navController

override fun onSupportNavigateUp() = currentNavController.navigateUp()

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
}
}
Loading

0 comments on commit b1817a7

Please sign in to comment.