ursus
10/24/2020, 9:35 PMursus
10/24/2020, 9:41 PMrefCount
behavior? I dont see how is it relevantwilliam
10/25/2020, 6:28 PMFlow<List<T>>
, can i convert it to Flow<T>
with something like flatten
on arrays on std lib?nwh
10/25/2020, 6:58 PMoffer
will throw an exception. I'm worried about the synchronization between the close call and the offer call. ie I need an atomic receiveAndClose (though I don't need it to be a channel)Florian
10/26/2020, 12:29 AMcatch
block in the UI, how do you avoid showing CancellationExceptions? Do you have to add an if check?hooliooo
10/26/2020, 3:21 PMval (firstImageBlobName, firstImageThumbnailBlobName, secondImageBlobName, secondImageThumbnailBlobName) = try {
coroutineScope {
AsyncImageUploads(
firstImageBlobName = async {
fileServiceInterface.uploadImage(
...
)
},
firstImageThumbnailBlobName = async {
fileServiceInterface.uploadImage(
...
)
},
secondImageBlobName = async {
fileServiceInterface.uploadImage(
...
)
},
secondImageThumbnailBlobName = async {
fileServiceInterface.uploadImage(
...
)
}
)
}
} catch (e: Exception) {
....
}
repository.save(
model.copy(
firstImage = firstImageRepository.save(
FirstImage(
imageURL = firstImageBlobName.await(),
thumbnailURL = firstImageThumbnailBlobName.await(),
model = model
)
),
secondImage = secondImageRepository.save(
SecondImage(
imageUrl = secondImageBlobName.await(),
thumbnailUrl = secondImageThumbnailBlobName.await(),
model = model
)
)
)
)
The issue is the upload takes around 40 seconds to finish 🤔 so I’m wondering if the async calls are happening concurrentlyvitaliy
10/26/2020, 5:26 PMBroadcastChannel
and Flow
. Essentially I’m looking for the navigate
to behave like rx PublishSubject
.
Issue: since navigate
flow is created from the channel, firstOrNull()
on it never finishes. I’m pretty new to coroutines and I will appreciate if somebody can have a look. Thanks!
import io.kotest.matchers.shouldBe
import kotlinx.coroutines.channels.BroadcastChannel
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.asFlow
import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import org.junit.jupiter.api.Test
class RetainStateTest {
val navigateChannel = BroadcastChannel<List<String>>(Channel.BUFFERED)
val navigate = navigateChannel.asFlow()
val data = listOf("blah", "foo")
@Test
fun `should not retain state`() {
runBlocking {
val jobPrecondition = launch {
navigate.firstOrNull() shouldBe data
}
navigateChannel.send(data)
jobPrecondition.join()
val job = launch {
navigate.firstOrNull() shouldBe null
}
job.join()
}
}
}
Vsevolod Tolstopyatov [JB]
10/26/2020, 6:54 PMStateFlow
and SharedFlow
are promoted to stable API
• Rewritten and fully optimized `Flow.combine`: better performance and no more SIGSEGV on Mediatek devices
• Various improvements and bug fixes
Full changelog: https://github.com/Kotlin/kotlinx.coroutines/releases/tag/1.4.0Yuri
10/26/2020, 8:42 PMSendChannel.offer should never throw
was fixed in 1.4.0 release?
https://github.com/Kotlin/kotlinx.coroutines/issues/974Yuri
10/26/2020, 8:43 PM-native-mt
library for 1.4.0 release for multi-threaded coroutines on KMM?Orhan Tozan
10/26/2020, 10:27 PMmutableSharedFlow.asSharedFlow()
bring over mutableSharedFlow as SharedFlow
?Tim Malseed
10/27/2020, 1:08 AMTwoClocks
10/27/2020, 2:12 AMkevin.cianfarini
10/27/2020, 3:07 AMonEach
with MutableStateFlow
and return a MutableStateFlow
?
My use case -- calling SavedStateHandle.getLiveData(key: String)
will automatically save new emissions to that live data into the saved state. I would like something like this to be possible with StateFlow
fun <T> SavedStateHandle.getStateFlow(key: String, defaultValue: T): MutableStateFlow<T> {
return MutableStateFlow(this[key] ?: defaultValue).onEach {
this[key] = it
}
}
However, onEach
returns a regular instance of Flow
. Is this something that's been discussed? If not, I'm more than willing to open an issue.Orhan Tozan
10/27/2020, 8:57 AMBroadcastChannel
in ViewModel in order to send events, I was using the non suspend channel.offer(..) to send them, but now with SharedFlow, there seems only be the suspending emit(...)
method. Does that mean all BroadcastChannel usage's can be migrated from
events.offer(...)
to Sharedflow?
viewModelScope.launch {
events.emit(...)
}
If so, that looks like more boilerplate for simple events sending 😕Paul Woitaschek
10/27/2020, 2:52 PMinline class A(val value: String)
fun main() {
runBlocking {
val aFlow = flowOf(A("Hello"))
combine(aFlow, aFlow) { a, b ->
a to b
}.toList()
}
}
Remy Benza
10/28/2020, 8:27 AMLukas Lechner
10/28/2020, 2:32 PMbsimmons
10/28/2020, 6:35 PMwhile
seems like an antipattern to me.) Any ideas?Florian
10/28/2020, 9:09 PMfirst()
because I only need to set the value from DataStore once, afterwards just clicking the checkbox will check/uncheck it. Does this make sense? Are there any situations where it will break?
2. Is the asynchronicity a problem? As far as I understand, you can't read from DataSore synchronously so this is the only option I can see.
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
[...]
viewLifecycleOwner.lifecycleScope.launch {
menu.findItem(R.id.action_hide_completed_tasks).isChecked =
viewModel.preferencesFlow.first().hideCompleted
}
}
Pablo
10/29/2020, 8:47 AMflow {
val resultService = service.getWhatever()
val mapStuff = resultService.mapper() <-- it throws NullPointer
emit(mapStuff)
}
Then on my viewmodel I have
usecase.execute(2)
.catch{do something}
.collect{expectedStuff}
What I'm missing? Do I have to add a .catch
on my datasource so the viewmodel is aware something crashed?Adrian Blanco
10/29/2020, 9:19 AMPublishSubject.create<T>()
to MutableSharedFlow<T>(replay = 0, extraBufferCapacity = 1)
, but what I can't wrap my head around is what is the use case for MutableSharedFlow<T>()
? (both parameters set to zero by default). It doesn't really seem to do anything.Florian
10/29/2020, 10:54 AM@ApplicationScope
@Provides
@Singleton
fun provideApplicationScope() = CoroutineScope(SupervisorJob())
Should I also inject the dispatcher that is used with this scope, and why?Marko Kovacevic
10/29/2020, 11:32 AMimplementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.0-M1")
coder82
10/29/2020, 1:12 PMFlorian
10/29/2020, 3:33 PMclass DeleteAllCompletedViewModel @ViewModelInject constructor(
private val taskDao: TaskDao,
@ApplicationScope private val applicationScope: CoroutineScope
) :
ViewModel() {
fun deleteCompletedTasks() = applicationScope.launch {
taskDao.deleteCompletedTasks()
}
}
nfrankel
10/29/2020, 8:23 PMCompletionStage
overall, my goal is to check whether i’ve an entity in the cache
and if it’s not, go to the database
the cache-checking returns a CompletionStage
and the database repo is a suspending function
how can i combine the two?
the best i can do is:
val person = cache.getAsync(id).await()
return if (person == null) repository.findById(id)
else person
and obviously, it’s not the right way to do it
i don’t find the correct operator
help greatly appreciated 🙂Florian
10/30/2020, 10:54 AM@Module
@InstallIn(ApplicationComponent::class)
object AppModule {
private lateinit var database: TaskDatabase
@Provides
@Singleton
fun provideDatabase(
app: Application,
@ApplicationScope applicationScope: CoroutineScope
): TaskDatabase {
database = Room.databaseBuilder(app, TaskDatabase::class.java, "task_database")
.fallbackToDestructiveMigration()
.addCallback(object : RoomDatabase.Callback() {
override fun onCreate(db: SupportSQLiteDatabase) {
super.onCreate(db)
val dao = database.taskDao()
applicationScope.launch {
dao.insert(Task("Wash the dishes"))
dao.insert(Task("Do the laundry"))
dao.insert(Task("Buy groceries"))
dao.insert(Task("Call mom"))
}
}
})
.build()
return database
}
@Provides
@Singleton
fun provideTaskDao(db: TaskDatabase) = db.taskDao()
@ApplicationScope
@Provides
@Singleton
fun provideApplicationScope() = CoroutineScope(SupervisorJob())
}
@Retention(AnnotationRetention.BINARY)
@Qualifier
annotation class ApplicationScope
Remy Benza
10/30/2020, 11:50 AMOleksii Yerastov
10/30/2020, 12:43 PMprivate val subject = BehaviorSubject.create<Int>().startWith(Observale.just(1))
but with SharedFlow
for example?
My use case is that I want to trigger specific function(in case of coroutines suspend
function) only once during creation of SharedFlow
or after first collector started collecting this flow. I cannot use onStart
or onSubscription
because there are more than 1 collector for this flow and thus, my specific function will be triggered for every collector.
So as a result a want to end up with something like
private val sharedFlow = MutableSharedFlow<Int>(replay = 1).startWith {
// some suspending call that will be called only once
}
and also get MutableSharedFlow
type for sharedFlow
variable to be able to call emit
/`tryEmit` for modification of cached value so all collectors get notified it changed.
Is it possible to implement this behavior?