Skip to content

Timber #55

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 4, 2021
Merged
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
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2019 Kotlin Android Open Source
Copyright (c) 2019-2021 Kotlin Android Open Source

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
1 change: 1 addition & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ dependencies {
implementation(deps.koin.android)

debugImplementation(deps.squareup.leakCanary)
implementation(deps.timber)

testImplementation(deps.test.junit)
androidTestImplementation(deps.test.androidxJunit)
Expand Down
7 changes: 7 additions & 0 deletions app/src/main/java/com/hoc/flowmvi/App.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import org.koin.android.ext.koin.androidContext
import org.koin.android.ext.koin.androidLogger
import org.koin.core.context.startKoin
import org.koin.core.logger.Level
import timber.log.Timber
import kotlin.time.ExperimentalTime

@FlowPreview
Expand All @@ -37,6 +38,12 @@ class App : Application() {
override fun onCreate() {
super.onCreate()

if (BuildConfig.DEBUG) {
Timber.plant(Timber.DebugTree())
} else {
// TODO(Timber): plant release tree
}

startKoin {
androidContext(this@App)

Expand Down
1 change: 1 addition & 0 deletions buildSrc/src/main/kotlin/deps.kt
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ object deps {
const val coil = "io.coil-kt:coil:1.2.1"
const val viewBindingDelegate = "com.github.hoc081098:ViewBindingDelegate:1.2.0"
const val flowExt = "io.github.hoc081098:FlowExt:0.0.7-SNAPSHOT"
const val timber = "com.jakewharton.timber:timber:5.0.1"

object arrow {
private const val version = "1.0.1"
Expand Down
2 changes: 2 additions & 0 deletions core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,7 @@ dependencies {
implementation(deps.lifecycle.commonJava8)
implementation(deps.lifecycle.runtimeKtx)

implementation(deps.timber)

addUnitTest()
}
4 changes: 2 additions & 2 deletions core/src/main/java/com/hoc/flowmvi/core/CollectIn.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.hoc.flowmvi.core

import android.util.Log
import androidx.fragment.app.Fragment
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
Expand All @@ -10,14 +9,15 @@ import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import timber.log.Timber

inline fun <T> Flow<T>.collectIn(
owner: LifecycleOwner,
minActiveState: Lifecycle.State = Lifecycle.State.STARTED,
crossinline action: suspend (value: T) -> Unit,
): Job = owner.lifecycleScope.launch {
owner.repeatOnLifecycle(state = minActiveState) {
Log.d("collectIn", "Start collecting $owner $minActiveState...")
Timber.d("Start collecting $owner $minActiveState...")
collect { action(it) }
}
}
Expand Down
4 changes: 2 additions & 2 deletions core/src/main/java/com/hoc/flowmvi/core/FlowBinding.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package com.hoc.flowmvi.core

import android.content.Context
import android.os.Looper
import android.util.Log
import android.view.View
import android.widget.EditText
import android.widget.Toast
Expand All @@ -17,6 +16,7 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.take
import timber.log.Timber
import kotlin.coroutines.EmptyCoroutineContext

internal fun checkMainThread() {
Expand All @@ -35,7 +35,7 @@ fun EditText.firstChange(): Flow<Unit> {
awaitClose {
Dispatchers.Main.dispatch(EmptyCoroutineContext) {
removeTextChangedListener(listener)
Log.d("###", "removeTextChangedListener $listener ${this@firstChange}")
Timber.d("removeTextChangedListener $listener $this")
}
}
}.take(1)
Expand Down
2 changes: 2 additions & 0 deletions data/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,7 @@ dependencies {
implementation(deps.koin.core)
implementation(deps.arrow.core)

implementation(deps.timber)

addUnitTest()
}
33 changes: 20 additions & 13 deletions data/src/main/java/com/hoc/flowmvi/data/UserRepositoryImpl.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.hoc.flowmvi.data

import android.util.Log
import arrow.core.Either
import arrow.core.left
import arrow.core.leftWiden
Expand All @@ -24,6 +23,7 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.scan
import kotlinx.coroutines.withContext
import timber.log.Timber
import java.io.IOException
import kotlin.time.Duration
import kotlin.time.ExperimentalTime
Expand Down Expand Up @@ -54,7 +54,7 @@ internal class UserRepositoryImpl(
factor = 2.0,
shouldRetry = { it is IOException }
) {
Log.d("###", "[USER_REPO] Retry times=$it")
Timber.d("[USER_REPO] Retry times=$it")
userApiService.getUsers().map(responseToDomain)
}
}
Expand All @@ -64,46 +64,53 @@ internal class UserRepositoryImpl(
val initial = getUsersFromRemote()

changesFlow
.onEach { Log.d("###", "[USER_REPO] Change=$it") }
.onEach { Timber.d("[USER_REPO] Change=$it") }
.scan(initial) { acc, change ->
when (change) {
is Change.Removed -> acc.filter { it.id != change.removed.id }
is Change.Refreshed -> change.user
is Change.Added -> acc + change.user
}
}
.onEach { Log.d("###", "[USER_REPO] Emit users.size=${it.size} ") }
.onEach { Timber.d("[USER_REPO] Emit users.size=${it.size} ") }
.let { emitAll(it) }
}
.map { it.right().leftWiden<UserError, Nothing, List<User>>() }
.catch { emit(errorMapper(it).left()) }
.catch {
Timber.tag("UserRepositoryImpl").e(it, "getUsers")
emit(errorMapper(it).left())
}

override suspend fun refresh() = Either.catch(errorMapper) {
override suspend fun refresh() = Either.catch {
getUsersFromRemote().let { changesFlow.emit(Change.Refreshed(it)) }
}
}.tapLeft { Timber.tag("UserRepositoryImpl").e(it, "refresh") }
.mapLeft(errorMapper)

override suspend fun remove(user: User) = Either.catch(errorMapper) {
override suspend fun remove(user: User) = Either.catch {
withContext(dispatchers.io) {
val response = userApiService.remove(user.id)
changesFlow.emit(Change.Removed(responseToDomain(response)))
}
}
}.tapLeft { Timber.tag("UserRepositoryImpl").e(it, "remove user=$user") }
.mapLeft(errorMapper)

override suspend fun add(user: User) = Either.catch(errorMapper) {
override suspend fun add(user: User) = Either.catch {
withContext(dispatchers.io) {
val body = domainToBody(user)
val response = userApiService.add(body)
changesFlow.emit(Change.Added(responseToDomain(response)))
extraDelay()
}
}
}.tapLeft { Timber.tag("UserRepositoryImpl").e(it, "add user=$user") }
.mapLeft(errorMapper)

override suspend fun search(query: String) = Either.catch(errorMapper) {
override suspend fun search(query: String) = Either.catch {
withContext(dispatchers.io) {
extraDelay()
userApiService.search(query).map(responseToDomain)
}
}
}.tapLeft { Timber.tag("UserRepositoryImpl").e(it, "search query=$query") }
.mapLeft(errorMapper)

private suspend inline fun extraDelay() = delay(400)
}
1 change: 1 addition & 0 deletions feature-add/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ dependencies {

implementation(deps.viewBindingDelegate)
implementation(deps.flowExt)
implementation(deps.timber)

addUnitTest()
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package com.hoc.flowmvi.ui.add

import android.content.Context
import android.content.Intent
import android.util.Log
import android.view.MenuItem
import androidx.core.view.isInvisible
import androidx.transition.AutoTransition
Expand All @@ -20,6 +19,7 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.merge
import org.koin.androidx.viewmodel.ext.android.viewModel
import timber.log.Timber

@ExperimentalCoroutinesApi
class AddActivity :
Expand All @@ -35,22 +35,21 @@ class AddActivity :
}

override fun handleSingleEvent(event: SingleEvent) {
Log.d("###", "Event=$event")
Timber.d("Event=$event")

return when (event) {
is SingleEvent.AddUserSuccess -> {
toast("Add success")
finish()
}
is SingleEvent.AddUserFailure -> {
Log.d("###", event.toString())
toast("Add failure")
}
}
}

override fun render(viewState: ViewState) {
Log.d("###", "ViewState=$viewState")
Timber.d("viewState=$viewState")

val emailErrorMessage = if (ValidationError.INVALID_EMAIL_ADDRESS in viewState.errors) {
"Invalid email"
Expand Down
6 changes: 3 additions & 3 deletions feature-add/src/main/java/com/hoc/flowmvi/ui/add/AddVM.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.hoc.flowmvi.ui.add

import android.util.Log
import androidx.core.util.PatternsCompat
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.viewModelScope
Expand Down Expand Up @@ -31,6 +30,7 @@ import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.scan
import kotlinx.coroutines.flow.stateIn
import timber.log.Timber

@ExperimentalCoroutinesApi
class AddVM(
Expand All @@ -46,13 +46,13 @@ class AddVM(
firstName = savedStateHandle.get<String?>(FIRST_NAME_KEY),
lastName = savedStateHandle.get<String?>(LAST_NAME_KEY),
)
Log.d(logTag, "[ADD_VM] initialVS: $initialVS")
Timber.tag(logTag).d("[ADD_VM] initialVS: $initialVS")

viewState = intentFlow
.toPartialStateChangesFlow()
.sendSingleEvent()
.scan(initialVS) { state, change -> change.reduce(state) }
.catch { Log.d(logTag, "[ADD_VM] Throwable: $it") }
.catch { Timber.tag(logTag).e(it, "[ADD_VM] Throwable: $it") }
.stateIn(viewModelScope, SharingStarted.Eagerly, initialVS)
}

Expand Down
1 change: 1 addition & 0 deletions feature-main/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ dependencies {
implementation(deps.viewBindingDelegate)
implementation(deps.flowExt)
implementation(deps.arrow.core)
implementation(deps.timber)

addUnitTest()
testImplementation(mviTesting)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.hoc.flowmvi.ui.main

import android.util.Log
import android.view.Menu
import android.view.MenuItem
import androidx.core.view.isVisible
Expand All @@ -27,6 +26,7 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.merge
import org.koin.android.ext.android.inject
import org.koin.androidx.viewmodel.ext.android.viewModel
import timber.log.Timber

@FlowPreview
@ExperimentalCoroutinesApi
Expand Down Expand Up @@ -81,7 +81,7 @@ class MainActivity :
)

override fun handleSingleEvent(event: SingleEvent) {
Log.d("MainActivity", "handleSingleEvent $event")
Timber.d("handleSingleEvent $event")
return when (event) {
SingleEvent.Refresh.Success -> toast("Refresh success")
is SingleEvent.Refresh.Failure -> toast("Refresh failure")
Expand All @@ -92,7 +92,7 @@ class MainActivity :
}

override fun render(viewState: ViewState) {
Log.d("MainActivity", "render $viewState")
Timber.d("render $viewState")

userAdapter.submitList(viewState.userItems)

Expand Down
6 changes: 3 additions & 3 deletions feature-main/src/main/java/com/hoc/flowmvi/ui/main/MainVM.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.hoc.flowmvi.ui.main

import android.util.Log
import androidx.lifecycle.viewModelScope
import com.hoc.flowmvi.domain.usecase.GetUsersUseCase
import com.hoc.flowmvi.domain.usecase.RefreshGetUsersUseCase
Expand Down Expand Up @@ -28,6 +27,7 @@ import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.scan
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.take
import timber.log.Timber

@FlowPreview
@ExperimentalCoroutinesApi
Expand All @@ -49,7 +49,7 @@ class MainVM(
.toPartialChangeFlow()
.sendSingleEvent()
.scan(initialVS) { vs, change -> change.reduce(vs) }
.catch { Log.d("###", "[MAIN_VM] Throwable: $it") }
.catch { Timber.tag(logTag).e(it, "[MAIN_VM] Throwable: $it") }
.stateIn(
viewModelScope,
SharingStarted.Eagerly,
Expand Down Expand Up @@ -79,7 +79,7 @@ class MainVM(
private fun Flow<ViewIntent>.toPartialChangeFlow(): Flow<PartialChange> =
shareWhileSubscribed().run {
val getUserChanges = defer(getUsersUseCase::invoke)
.onEach { either -> Log.d("###", "[MAIN_VM] Emit users.size=${either.map { it.size }}") }
.onEach { either -> Timber.d("[MAIN_VM] Emit users.size=${either.map { it.size }}") }
.map { result ->
result.fold(
ifLeft = { PartialChange.GetUser.Error(it) },
Expand Down
1 change: 1 addition & 0 deletions feature-search/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ dependencies {
implementation(deps.viewBindingDelegate)
implementation(deps.flowExt)
implementation(deps.arrow.core)
implementation(deps.timber)

addUnitTest()
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package com.hoc.flowmvi.ui.search
import android.content.Context
import android.content.Intent
import android.content.res.Configuration
import android.util.Log
import android.view.Menu
import android.view.MenuItem
import androidx.appcompat.widget.SearchView
Expand All @@ -30,6 +29,7 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.flow.onEach
import org.koin.androidx.viewmodel.ext.android.viewModel
import timber.log.Timber
import kotlin.time.ExperimentalTime

@ExperimentalCoroutinesApi
Expand Down Expand Up @@ -79,7 +79,7 @@ class SearchActivity :
override fun viewIntents(): Flow<ViewIntent> = merge(
searchViewQueryTextEventChannel
.consumeAsFlow()
.onEach { Log.d("SearchActivity", "Query $it") }
.onEach { Timber.d("Query $it") }
.map { ViewIntent.Search(it.query.toString()) },
binding.retryButton.clicks().map { ViewIntent.Retry },
)
Expand Down
Loading