Created
September 7, 2020 17:49
-
-
Save houssemzaier/1a1b1ee428a18fb4d20304aba00c6a98 to your computer and use it in GitHub Desktop.
Without unit Testing just run as jvm console app
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.raywenderlich.kotlin.coroutines | |
import androidx.arch.core.executor.ArchTaskExecutor | |
import androidx.arch.core.executor.TaskExecutor | |
import androidx.lifecycle.* | |
import kotlinx.coroutines.* | |
import kotlin.coroutines.CoroutineContext | |
@ExperimentalCoroutinesApi | |
class Main3 { | |
fun mainTest() = runBlocking { | |
val job1 = GlobalScope.launch(coroutineContext) { | |
val fragment = Fragment() | |
fragment.onActivityCreated(coroutineContext) | |
delay(66_666) | |
} | |
val job2 = GlobalScope.launch(coroutineContext) { | |
var timeout: Long = 20_000 | |
while (timeout > 0) { | |
delay(1_000) | |
println("timeout ${timeout / 1_000} ") | |
timeout -= 1_000 | |
} | |
} | |
joinAll(job1, job2) | |
} | |
} | |
fun main() = runBlocking { | |
ArchTaskExecutor.getInstance().setDelegate(object : TaskExecutor() { | |
override fun executeOnDiskIO(runnable: Runnable) { | |
runnable.run() | |
} | |
override fun postToMainThread(runnable: Runnable) { | |
runnable.run() | |
} | |
override fun isMainThread(): Boolean { | |
return true | |
} | |
}) | |
//Dispatchers.setMain(Dispatchers.Default) | |
val job1 = GlobalScope.launch { | |
val fragment = Fragment() | |
fragment.onActivityCreated() | |
} | |
val job2 = GlobalScope.launch { | |
var timeout: Long = 20_000 | |
while (timeout > 0) { | |
delay(1_000) | |
println("timeout ${timeout / 1_000} ") | |
timeout -= 1_000 | |
} | |
} | |
// while (job2.isActive){} | |
joinAll(job1, job2) | |
} | |
class Fragment : LifecycleOwner { | |
private val lifecycle = LifecycleRegistry(this) | |
init { | |
lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_RESUME) | |
} | |
suspend fun onActivityCreated(_coroutineContext: CoroutineContext? = null) { | |
val repo = Repository() | |
val loadContentUseCase1 = LoadContentUseCase1(repo) | |
val loadContentUseCase2 = LoadContentUseCase2(repo) | |
val loadContentUseCase3 = LoadContentUseCase3(repo) | |
val vm = ViewModel( | |
loadContentUseCase1, | |
loadContentUseCase2, | |
loadContentUseCase3 | |
) | |
vm.loadData(_coroutineContext) | |
//solution2: expose a LiveData of DataStructure wrapper that wraps the needed data received in order | |
vm.content.observe(this) { content -> | |
when (content) { | |
is Page.Error -> { | |
println("no content it should show error page") | |
} | |
is Page.Loading -> { | |
println("all content is loading ...") | |
} | |
else -> { | |
println("all content is $content") | |
} | |
} | |
} | |
} | |
override fun getLifecycle(): Lifecycle = lifecycle | |
} | |
class ViewModel(private val useCase1: LoadContentUseCase1, | |
private val useCase2: LoadContentUseCase2, | |
private val useCase3: LoadContentUseCase3 | |
) : CoroutineScope { | |
private val handler = CoroutineExceptionHandler { _, throwable -> | |
println("Main3 ParentCoroutine is handling $throwable") | |
} | |
private val job = SupervisorJob() | |
override val coroutineContext: CoroutineContext | |
get() = handler + job | |
private val _content = MutableLiveData<Page>() | |
val content: LiveData<Page> = _content | |
suspend fun loadData(_coroutineContext: CoroutineContext? = null) { | |
_content.value = Page.Loading | |
launch(_coroutineContext ?: coroutineContext) { | |
val useCase1Response = async { useCase1() } | |
println("useCase1Response $useCase1Response") | |
val useCase2Response = async { useCase2() } | |
println("useCase2Response $useCase2Response") | |
val useCase3Response = async { useCase3() } | |
println("useCase3Response $useCase3Response") | |
val content1 = useCase1Response.await() | |
val content2 = useCase2Response.await() | |
val content3 = useCase3Response.await() | |
if (content1.isEmpty() && content2.isEmpty() && content3.isEmpty()) { | |
_content.value = Page.Error | |
} else { | |
_content.value = Page.Content(content1, content2, content3) | |
} | |
} | |
} | |
fun onClear() { | |
job.cancel() | |
} | |
} | |
sealed class Page { | |
object Loading : Page() | |
object Error : Page() | |
data class Content( | |
val content1: String?, | |
val content2: String?, | |
val content3: String?, | |
) : Page() | |
} | |
class LoadContentUseCase1(private val repository: Repository) { | |
suspend operator fun invoke() = repository.loadContent1() | |
} | |
class LoadContentUseCase2(private val repository: Repository) { | |
suspend operator fun invoke() = repository.loadContent2() | |
} | |
class LoadContentUseCase3(private val repository: Repository) { | |
suspend operator fun invoke() = repository.loadContent3() | |
} | |
class Repository { | |
suspend fun loadContent1(): String { | |
println("loadContent1 is started") | |
delay(1000) | |
println("loadContent1 is finished") | |
return "content 1" | |
} | |
suspend fun loadContent2(): String { | |
println("loadContent2 is started") | |
delay(2000) | |
println("loadContent2 is finished") | |
return "content 2" | |
} | |
suspend fun loadContent3(): String { | |
println("loadContent3 is started") | |
delay(3000) | |
println("loadContent3 is finished") | |
return "content 3" | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment