Giter Site home page Giter Site logo

rbusarow / dispatch Goto Github PK

View Code? Open in Web Editor NEW
136.0 136.0 6.0 8.83 MB

Automatic CoroutineDispatcher injection and extensions for kotlinx.coroutines

Home Page: https://rbusarow.github.io/Dispatch/

License: Apache License 2.0

Kotlin 99.27% Java 0.39% Shell 0.35%

dispatch's Introduction

My active projects

Ultra-fast dependency graph validation and tree-shaking for Gradle

latest version last commit watchers stars

Android injection using the Anvil compiler plugin

latest version last commit watchers stars

Automatic CoroutineDispatcher injection and extensions for kotlinx.coroutines

latest version last commit watchers stars

Lazy Kotlin delegates which automatically reset with a test lifecycle

latest version last commit watchers stars

Utility for making Dependabot updates with with Gradle's libs.versions.toml

latest version last commit watchers stars

dispatch's People

Contributors

dependabot[bot] avatar rbusarow avatar renovate[bot] avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

dispatch's Issues

Incorrect dispatch-android-viewmodel package

The manifest declares the base package to be dispatch.android.viewmodel, which is correct. But the actual package in code is dispatch.android.lifecycle as it is in the AndroidX version.

Consider removing the context parameter in coroutine builders

As of 1.0.0-beta01, builders such as launchDefault(...) take a first parameter of context: CoroutineContext = EmptyCoroutineContext. The full code:

public fun CoroutineScope.launchDefault(
  context: CoroutineContext = EmptyCoroutineContext,
  start: CoroutineStart = CoroutineStart.DEFAULT,
  block: suspend CoroutineScope.() -> Unit
): Job = launch(coroutineContext.dispatcherProvider.default + context, start, block)

This is to preserve the same signature of the original functions (async(...) is the same) as in the kotlinx-coroutines library. Except even Roman says that was a mistake and it only exists today for backwards compatibility.

These new functions are a perfect excuse to drop the parameter, except that there are still other uses for that context other than incorrectly specifying the Job, or overwriting the dispatcher. What about passing in a custom exception handler or a CoroutineName for debugging? Or what about other custom CoroutineContext.Elements?

One option would be to add some require(...)'s to the functions, which throw an exception if the passed CoroutineContext contains a Job or a ContinuationInterceptor. This is done in a few places in the Flow api. But then we're introducing a runtime exception instead of a checked one.

Another option might be to ignore any Job or ContinuationInterceptor properties in the passed context, adding a warning to the comments. This has its own issues, since technically we add some complexity to the fold, and if the user doesn't read the comment, they may miss that their Job or ContinuationInterceptor is being ignored when that's what they really wanted.

I'm leaning toward the require(...) but still undecided.

runBlockingTestProvided() must add the TestCoroutineDispatcher to the context

The TestCoroutineDispatcher used to create the TestDispatcherProvider is not added to the context. Since there is no existing dispatcher in the context, the called runBlockingTest() will create its own TestCoroutineDispatcher.

As a consequence, any calls to advanceTime...() will not work correctly since they are performed on a different dispatcher. The following test fails with an UncompletedCoroutinesError

    @Test
    @ExperimentalCoroutinesApi
    fun advanceTimeIssue() = runBlockingTestProvided {
        delayOnProvidedMain()
        advanceTimeBy(1000)
    }

    fun CoroutineScope.delayOnProvidedMain() {
        launch(dispatcherProvider.main) {
            delay(1000)
        }
    }

In order to fix this situation, you must add the testDispatcher used for the provider also to the context, see this working example:

    @ExperimentalCoroutinesApi
    private fun contextWithProvider(): CoroutineContext {
        val testDispatcher = TestCoroutineDispatcher()
        val provider = TestDispatcherProvider(testDispatcher)
        return EmptyCoroutineContext + testDispatcher + provider
    }

    @Test
    @ExperimentalCoroutinesApi
    fun advanceTimeIssueFixed() = runBlockingTest(contextWithProvider()) {
        delayOnProvidedMain()
        advanceTimeBy(1000)
    }

New name for library and base package

"DispatcherProvider" isn't a very good name. For the interface, it's nice and descriptive, and a fairly common name for what it does, so I'm okay with leaving that alone.

As a library, though, it feels too descriptive to the point of being limiting. I would like to add functionality to the library with more modules and artifacts, where this new content is related to but definition not core to the functionality of DispatcherProvider.

I've been using the name dispatch as a base package for a few days, and I more or less like it.

The resultant package structure would look something like this:

import description
dispatch.core.* Core functionality, naturally
dispatch.core.test.* core testing functionality
dispatch.extensions.* essentially ktx for coroutines
dispatch.core.test.android.* IdlingDispatcher + dispatch.core.test
dispatch.android.* (runtime artifact) fork of androidx.lifecycle.runtime but more extensible and without the leaky pausing dispatcher
dispatch.android.* (viewModel artifact) fork of androidx.lifecycle.viewmodel but more extensible

Artifact BOM

I just found your useful project here and figured that because of the number of artifacts it provides it might be useful to provide a BOM (bill of material) that lists all versions of all artifacts in a central place.

Such a thing could then be consumed in a Gradle multi project build through

// my.platform.project:production
plugins {
    id("java-platform")
}

dependencies {
    api(platform("com.rickbusarow.dispatch:dispatch-bom:1.0.0-beta09"))
}

and this could be referenced in individual module files like so:

dependencies {
    implementation(platform("my.platform.project:production"))

    implementation("com.rickbusarow.dispatch:dispatch-core")
}

Creating and publishing such a BOM should be fairly easy. Thanks!

ViewLifecycleCoroutineScope

Fragment's double lifecycle issue affects LifecycleCoroutineScope (Androidx's or Dispatch's) as well.

Consider this example from the official docs:

class MyFragment: Fragment() {
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        viewLifecycleOwner.lifecycleScope.launch {
            val params = TextViewCompat.getTextMetricsParams(textView)
            val precomputedText = withContext(Dispatchers.Default) {
                PrecomputedTextCompat.create(longTextContent, params)
            }
            TextViewCompat.setPrecomputedText(textView, precomputedText)
        }
    }
}

Because the View lifecycle is odd, we either need to wait until onViewCreated in order to access it, or we need to use viewLifecycleOwnerLiveData. Using the former, the developer must use ordinary lifecycle callback functions in order to guarantee the View's existence. This is inconsistent with the rest of lifecycle coroutines, which could be executed from inside init { }.

The alternative approach of observing viewLifecycleOwnerLiveData seems better. It allows the use of init { }. Also, since onViewCreated must happen after onAttach(), this means that an AAC viewModel initialized via by viewModels may be accessed safely. This means we can write the following:

class MyFragment @Inject constructor(
  coroutineScope: MainImmediateCoroutineScope
) : Fragment {

  val viewModel: MyViewModel by viewModels()

  init {
    coroutineScope.withViewLifecycle  { // this: ViewLifecycleCoroutineScope
      // safely reference this directly inside the constructor because this will never invoke before onAttach
      viewModel.someFlow.onEach {
        // ...
      }.launchOnStart() // ViewLifecycleCoroutineScope-specific functions for lifecycle-aware collection of Flow
    }
  }
}

Add Lint rules warning against accessing the Dispatchers object or creating CoroutineScope without a DispatcherProvider

Any access to the Dispatchers object breaks tests. This happens if we create a CoroutineScope without giving it a DispatcherProvider, or if we hard-code stuff like this:

class SomeClass {

  // We can still use `.dispatcherProvider` with this coroutineScope,
  // but it always returns a default implementation
  val coroutineScope = CoroutineScope(Job() + Dispatchers.Main)

  // This obviously accesses a hard-coded dispatcher
  fun foo() = coroutineScope.launch(Dispatchers.Default) { ... }
}

This is relatively easy to catch with Lint rules, but adding that rule to the main artifact will immediately create a warning for any code which has not been refactored.

Open Items

  • Should a Lint rule go into its own artifact, effectively allowing the user to opt in by adding the dependency? Or should it just be published as part of the core artifact?

update for AAC Lifecycle 2.5.0

The AndroidX ViewModel library offers a viewModelScope extension function to provide an auto-cancelled CoroutineScope, but again, this CoroutineScope is hard-coded and uses Dispatchers.Main. This limitation needn't exist.

This is no longer true w/ Lifecycle 2.5.0+:
https://developer.android.com/jetpack/androidx/releases/lifecycle#2.5.0

"addCloseable() API and a new constructor overload that allow you to add one or more Closeable objects to the ViewModel that will be closed when the ViewModel is cleared without requiring any manual work in onCleared()."
So you can pass in a Closable coroutinescope to a viewmodel's constructor.

Question: Testing coroutine creation

Hello @RBusarow ,
first of all, thanks for the great library.

I have a question regarding testing:

I have the following test using JUnit5

     @Test
    @DisplayName("Testing storing into DB")
    fun storeTest() = testProvided { // also tried others methods like runBlockingProvided
        notificationManager.storeNotification(getSimpleNotification())
        coVerify { // using Mockk library
            notificationsDatabaseWrapper.insert(any())
        }
    }

testing the following method

    override fun storeNotification(notificationData: NotificationData) {
        IOCoroutineScope().launch { // scope from Dispatchers library
            delay(3000) // just to show that its not blocking
            notificationsDatabaseWrapper.insert(notificationData)
        }
    }

howEver its failing unless I specify like 3300 timeout in coVerify which indicates that its not getting blocked.
I am not injecting the dispatcher/scope into the class where I have storeNotification, neither do I have any setup for the tests regarding dispatchers. Using JUnit5. So the question is, how to test that case? Any help will be appreciated.

Regular suspend functions are getting blocked properly

DefaultDispatcherProvider

DefaultDispatcherProvider is currently a class which implements DispatcherProvider, just returning the corresponding values from the Dispatchers singleton.

The idea is to change DefaultDispatcherProvider into a singleton object, with atomic get and set functions.

In the library, every DispatcherProvider reference goes through this extension property:

public val CoroutineContext.dispatcherProvider: DispatcherProvider
  get() = get(DispatcherProvider) ?: DefaultDispatcherProvider()

Which can be converted to:

public val CoroutineContext.dispatcherProvider: DispatcherProvider
  get() = get(DispatcherProvider) ?: DefaultDispatcherProvider.get()

This allows every "miss" when referencing the DispatcherProvider to return a global singleton instance. In other words, developers don't need to inject or service-locate CoroutineScopes or CoroutineContexts in order to have control. All that's needed is to set the singleton on app launch, or to set/reset the instance in tests.

@Test
fun `my test`() = runBlocking {

  DefaultDispatcherProvider.set(TestDispatcherProvider())
  
  withMain {
    // this would normally crash without using Dispatchers.setMain
    // but "main" here comes from the TestDispatcherProvider created above -- not Dispatchers.Main
  }
  
  DefaultDispatcherProvider.reset() // from dispatch-test
} 

This would be a breaking change in that the DefaultDispatcherProvider type would be re-purposed, and would no longer implement DispatcherProvider. The existing DefaultDispatcherProvider constructor can be recreated as a companion object operator fun invoke() factory which is marked as deprecated, so it will continue to compile. This deprecated function will be removed before the 1.0 release.

withViewLifecycleScope does not continue collection after the first view LifecycleScopeOwner is destroyed

Given this code:

class MyFragment: Fragment() {

  val myViewModel = ...

  init {
    receiverScope.withViewLifecycle(this) {
      myViewModel.myFlow
        .onEach { ... }
        .launchOnStart()
    }
  }
}

Collection will happen after the fragment is initially started. If the fragment is pushed to the backstack and the View is destroyed, then the coroutine which observes the lifecycle is cancelled and not restarted. If the fragment is brought back into view and a new viewLifecycleOwner is created, it will not re-start collection.

Memory leak in LifecycleCoroutineScopeStore

Hi, loved finding your library! I was just contemplating writing something like it until I came across it and it seemed to match perfectly with what I was looking for. I did however come across a few issues that I wanted to flag to see if they're on your radar - notably with LifecycleCoroutineScopeStore.

Each access of LifecycleOwner.lifecycleScope for a distinct Lifecycle (any individual instance of a Fragment, Activity, etc) results in an insertion to map which is never removed, leaking both the Lifecycle key and the LifecycleCoroutineScope value.

A separate issue is that LifecycleCoroutineScopeStore is not thread-safe, because the "get or put" logic as implemented is not atomic. Multiple concurrent invocations of get may return separate instances of LifecycleCoroutineScope, but only one of them will get stored in map. A possible fix would be to use Kotlin's ConcurrentMap.getOrPut or the built-in computeIfAbsent.

LifecycleCoroutineScope's argument should be a CoroutineContext instead of MainImmediateCoroutineScope

The library is able to construct its own MainImmediateContext (SupervisorJob() + DefaultDispatcherProvider().let { it + it.mainImmediate }), so there's no need to require a full MainImmediateCoroutineScope argument. It is fine, though, to overload the constructor or factory so as to accept a CoroutineScope as well.

By taking any sort of CoroutineScope or CoroutineContext, it's easy to inherit any additional Elements while ensuring that the minimum requirements are there. So, for any CoroutineContext argument, its Elements will be re-used, except:

    1. If a DispatcherProvider element isn't present, a DefaultDispatcherProvider will be added.
    1. If a Job element isn't present, a SupervisorJob will be added.
    1. If the ContinuationInterceptor does not match the one referenced by the [possibly new] DispatcherProvider.mainImmediate property, it will be updated to match.

Add an optional CoroutineContext parameter to Lifecycle-aware functions

This affects three families of functions:

LifecycleCoroutineScope.launchOn______
LifecycleOwner.onNext______
Lifecycle.onNext______

They currently have no way to actually change the context in any way -- whether that's the dispatcher or something else like an exception handler. This is consistent with the androidx-lifecycle-runtime library, but it's inconsistent with anything from the kotlinx-coroutines library. There's also no reason for it. While I'm sure the majority of use-cases will always be just a continuation of the same context, I'm sure there are use-cases for alternatives.

Proposed change

Add an optional context: CoroutineContext = EmptyCoroutineContext parameter to all the permutations of the above functions. Make this the first parameter to match the convention in the kotlinx-coroutines library.

Breaking change

This introduces a minor breaking change. In any place where there's code like this:

lifecycleScope.launchOnResume(MinimumStatePolicy.CANCEL) { ... }

the argument won't resolve, because the first argument is now a CoroutineContext instead of a MinimumStatePolicy. If the existing code uses named arguments, it won't be a problem.

dispatchLifecycleScope.kt sometimes fails to catch FlowCancellationException

Fatal Exception: java.lang.RuntimeException: Unable to pause activity {*******Activity}: dispatch.android.lifecycle.internal.FlowCancellationException: Flow was aborted
       at android.app.ActivityThread.performPauseActivityIfNeeded(ActivityThread.java:4124)
       at android.app.ActivityThread.performPauseActivity(ActivityThread.java:4090)
       at android.app.ActivityThread.performPauseActivity(ActivityThread.java:4064)
       at android.app.ActivityThread.handlePauseActivity(ActivityThread.java:4038)
       at android.app.ActivityThread.-wrap16()
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1708)
       at android.os.Handler.dispatchMessage(Handler.java:105)
       at android.os.Looper.loop(Looper.java:164)
       at android.app.ActivityThread.main(ActivityThread.java:6938)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)
Caused by dispatch.android.lifecycle.internal.FlowCancellationException: Flow was aborted
       at dispatch.android.lifecycle.internal.DispatchLifecycleScopeKt$onNext$2.invokeSuspend(dispatchLifecycleScope.kt:61)
       at dispatch.android.lifecycle.internal.DispatchLifecycleScopeKt$onNext$2.invoke(:10)
       at dispatch.android.lifecycle.internal.DispatchLifecycleScopeKt$onEachLatest$1.invokeSuspend(dispatchLifecycleScope.kt:146)
       at dispatch.android.lifecycle.internal.DispatchLifecycleScopeKt$onEachLatest$1.invoke(:12)
       at kotlinx.coroutines.flow.internal.ChannelFlowTransformLatest$flowCollect$3$invokeSuspend$$inlined$collect$1$lambda$1.invokeSuspend(Merge.kt:34)
       at kotlinx.coroutines.flow.internal.ChannelFlowTransformLatest$flowCollect$3$invokeSuspend$$inlined$collect$1$lambda$1.invoke(:10)
       at kotlinx.coroutines.intrinsics.UndispatchedKt.startCoroutineUndispatched(Undispatched.kt:55)
       at kotlinx.coroutines.CoroutineStart.invoke(CoroutineStart.kt:111)
       at kotlinx.coroutines.AbstractCoroutine.start(AbstractCoroutine.kt:158)
       at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch(Builders.common.kt:56)
       at kotlinx.coroutines.BuildersKt.launch(:1)
       at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch$default(Builders.common.kt:49)
       at kotlinx.coroutines.BuildersKt.launch$default(:1)
       at kotlinx.coroutines.flow.internal.ChannelFlowTransformLatest$flowCollect$3$invokeSuspend$$inlined$collect$1.emit(Collect.kt:138)
       at kotlinx.coroutines.flow.DistinctFlowImpl$collect$$inlined$collect$1.emit(Collect.kt:137)
       at kotlinx.coroutines.flow.internal.SafeCollectorKt$emitFun$1.invoke(SafeCollector.kt:15)
       at kotlinx.coroutines.flow.internal.SafeCollectorKt$emitFun$1.invoke(:4)
       at kotlinx.coroutines.flow.internal.SafeCollector.emit(SafeCollector.kt:77)
       at kotlinx.coroutines.flow.internal.SafeCollector.emit(SafeCollector.kt:59)
       at dispatch.core.FlowKt$flowOnMainImmediate$1$invokeSuspend$$inlined$collect$1.emit(Collect.kt:133)
       at kotlinx.coroutines.flow.FlowKt__ChannelsKt.emitAllImpl$FlowKt__ChannelsKt(Channels.kt:61)
       at kotlinx.coroutines.flow.FlowKt__ChannelsKt$emitAllImpl$1.invokeSuspend(:11)
       at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
       at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
       at dispatch.android.espresso.IdlingDispatcher$dispatch$$inlined$Runnable$1.run(Runnable.kt:21)
       at android.os.Handler.handleCallback(Handler.java:789)
       at android.os.Handler.dispatchMessage(Handler.java:98)
       at android.os.Looper.loop(Looper.java:164)
       at android.app.ActivityThread.main(ActivityThread.java:6938)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)

junit-vintage-engine as runtimeOnly dependency

I discovered some quirks in my setup when I added the dispatch-test artifact to my test classpath. This artifact transitively pulls org.junit.vintage:junit-vintage-engine into the test compile classpath, which - by documentation - should only reside in the test runtime's classpath (i.e. testRuntimeOnly). The quirk now was that when I added dispatch-test, my tests were executed as wanted (as the JUnit4 runtime was on the classpath), but as soon as I removed it, tests weren't executed anymore.

The solution for me was obviously to depend on junit-vintage-engine myself, but I thought it might be a good idea to get rid of it in the transitive classpath as well.

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Rate-Limited

These updates are currently rate-limited. Click on a checkbox below to force their creation now.

  • Update dependency androidx.savedstate:savedstate to v1.2.1
  • Update dependency com.google.auto:auto-common to v1.2.2
  • Update androidx.fragment.version to v1.7.1 (androidx.fragment:fragment-testing, androidx.fragment:fragment-ktx, androidx.fragment:fragment)
  • Update androidx.navigation.version to v2.7.7 (androidx.navigation:navigation-ui-ktx, androidx.navigation:navigation-runtime-ktx, androidx.navigation:navigation-fragment-ktx, androidx.navigation:navigation-compose, androidx.navigation:navigation-common)
  • Update androidx.paging to v3.3.0 (androidx.paging:paging-common-ktx, androidx.paging:paging-runtime-ktx)
  • Update androidx.room to v2.6.1 (androidx.room:room-testing, androidx.room:room-runtime, androidx.room:room-paging, androidx.room:room-ktx, androidx.room:room-compiler, androidx.room:room-common)
  • Update androidx.test.core (androidx.test.ext:truth, androidx.test:runner, androidx.test:rules, androidx.test:core)
  • Update androidx.test.espresso to v3.5.1 (androidx.test.espresso:espresso-web, androidx.test.espresso:espresso-intents, androidx.test.espresso:espresso-idling-resource, androidx.test.espresso:espresso-core, androidx.test.espresso:espresso-contrib)
  • Update androidx.work.version to v2.9.0 (androidx.work:work-testing, androidx.work:work-runtime-ktx, androidx.work:work-runtime)
  • Update babel monorepo to v7.24.6 (@babel/core, @babel/helper-compilation-targets)
  • Update cirrus-actions/rebase action to v1.8
  • Update coil to v2.6.0 (io.coil-kt:coil-gif, io.coil-kt:coil, io.coil-kt:coil-compose)
  • Update dependency androidx.annotation:annotation to v1.8.0
  • Update dependency androidx.appcompat:appcompat to v1.6.1
  • Update dependency androidx.arch.core:core-testing to v2.2.0
  • Update dependency androidx.core:core-ktx to v1.13.1
  • Update dependency androidx.paging:paging-common to v3.3.0
  • Update dependency androidx.paging:paging-runtime to v3.3.0
  • Update dependency androidx.recyclerview:recyclerview to v1.3.2
  • Update dependency androidx.test.uiautomator:uiautomator to v2.3.0
  • Update dependency androidx.viewpager2:viewpager2 to v1.1.0
  • Update dependency app.cash.turbine:turbine to v0.13.0
  • Update dependency com.android.tools.build:gradle to v7.4.2
  • Update dependency com.autonomousapps.dependency-analysis to v1.32.0
  • Update dependency com.github.ben-manes.versions to v0.51.0
  • Update dependency com.github.tschuchortdev:kotlin-compile-testing to v1.6.0
  • Update dependency com.google.android.material:material to v1.12.0
  • Update dependency com.google.auto.service:auto-service to v1.1.1
  • Update dependency com.google.auto.service:auto-service-annotations to v1.1.1
  • Update dependency com.google.devtools.ksp:symbol-processing-gradle-plugin to v1.9.24-1.0.20
  • Update dependency com.google.truth:truth to v1.4.2
  • Update dependency com.osacky.doctor to v0.10.0
  • Update dependency com.vanniktech:gradle-maven-publish-plugin to v0.28.0
  • Update dependency commons-io:commons-io to v2.16.1
  • Update dependency dev.zacsweers.autoservice:auto-service-ksp to v1.1.0
  • Update dependency gradle to v7.6.4
  • Update dependency io.mockk:mockk to v1.13.11
  • Update dependency mermaid to v9.4.3
  • Update dependency net.swiftzer.semver:semver to v1.3.0
  • Update dependency org.jetbrains.kotlinx.binary-compatibility-validator to v0.14.0
  • Update dependency org.jetbrains.kotlinx:atomicfu-gradle-plugin to v0.24.0
  • Update dependency org.objenesis:objenesis to v3.4
  • Update dependency org.robolectric:robolectric to v4.12.2
  • Update detekt to v1.23.6 (io.gitlab.arturbosch.detekt, io.gitlab.arturbosch.detekt:detekt-test-utils, io.gitlab.arturbosch.detekt:detekt-test, io.gitlab.arturbosch.detekt:detekt-gradle-plugin, io.gitlab.arturbosch.detekt:detekt-cli, io.gitlab.arturbosch.detekt:detekt-api)
  • Update docusaurus monorepo to v2.4.3 (@docusaurus/core, @docusaurus/plugin-content-docs, @docusaurus/plugin-content-pages, @docusaurus/preset-classic, @docusaurus/theme-classic)
  • Update dokka to v1.9.20 (org.jetbrains.dokka, org.jetbrains.dokka:dokka-gradle-plugin)
  • Update dropbox.dependencyGuard to v0.5.0 (com.dropbox.dependency-guard, com.dropbox.dependency-guard:dependency-guard)
  • Update google.dagger to v2.51.1 (com.google.dagger:dagger-compiler, com.google.dagger:dagger)
  • Update kotest to v5.9.0 (io.kotest:kotest-runner-junit5-jvm, io.kotest:kotest-property-jvm, io.kotest:kotest-common-jvm, io.kotest:kotest-assertions-shared-jvm, io.kotest:kotest-assertions-core-jvm)
  • Update kotlin monorepo (org.jetbrains.kotlinx:kotlinx-metadata-jvm, org.jetbrains.kotlin.jvm, org.jetbrains.kotlin:kotlin-test, org.jetbrains.kotlin:kotlin-test-common, org.jetbrains.kotlin:kotlin-stdlib-jdk8, org.jetbrains.kotlin:kotlin-reflect, org.jetbrains.kotlin:kotlin-gradle-plugin-api, org.jetbrains.kotlin:kotlin-gradle-plugin, org.jetbrains.kotlin:kotlin-compiler-embeddable, org.jetbrains.kotlin:kotlin-annotation-processing-embeddable)
  • Update kotlinx.coroutines to v1.8.1 (org.jetbrains.kotlinx:kotlinx-coroutines-test, org.jetbrains.kotlinx:kotlinx-coroutines-play-services, org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm, org.jetbrains.kotlinx:kotlinx-coroutines-jdk8, org.jetbrains.kotlinx:kotlinx-coroutines-core, org.jetbrains.kotlinx:kotlinx-coroutines-android)
  • Update kotlinx.knit to v0.5.0 (org.jetbrains.kotlinx:kotlinx-knit-test, org.jetbrains.kotlinx:kotlinx-knit)
  • Update ktlint.gradle to v11.6.1 (org.jlleitschuh.gradle.ktlint, org.jlleitschuh.gradle:ktlint-gradle)
  • Update okhttp monorepo to v4.12.0 (com.squareup.okhttp3:mockwebserver, com.squareup.okhttp3:logging-interceptor, com.squareup.okhttp3:okhttp)
  • Update plugin com.gradle.enterprise to v3.17.4
  • Update react monorepo to v18.3.1 (react, react-dom)
  • Update square.moshi to v1.15.1 (com.squareup.moshi:moshi-kotlin-codegen, com.squareup.moshi:moshi-kotlin, com.squareup.moshi:moshi, com.squareup.moshi:moshi-adapters)
  • Update square.okio to v3.9.0 (com.squareup.okio:okio-bom, com.squareup.okio:okio)
  • Update square.retrofit to v2.11.0 (com.squareup.retrofit2:converter-moshi, com.squareup.retrofit2:retrofit-mock, com.squareup.retrofit2:retrofit)
  • Update styfle/cancel-workflow-action action to v0.12.1
  • Update zacSweers.moshix to v0.27.1 (dev.zacsweers.moshix:moshi-sealed-codegen, dev.zacsweers.moshix:moshi-sealed-runtime)
  • Update actions/checkout action to v4
  • Update actions/setup-java action to v4
  • Update actions/setup-node action to v4
  • Update actions/upload-artifact action to v4
  • Update crazy-max/ghaction-github-pages action to v4
  • Update dependency @mdx-js/react to v3
  • Update dependency androidx.paging:paging-compose to v3
  • Update dependency app.cash.turbine:turbine to v1
  • Update dependency clsx to v2
  • Update dependency com.android.tools.build:gradle to v8
  • Update dependency com.dorongold.task-tree to v3
  • Update dependency com.google.devtools.ksp:symbol-processing-gradle-plugin to v2
  • Update dependency gradle to v8
  • Update dependency mdx-mermaid to v2
  • Update dependency mermaid to v10
  • Update dependency net.swiftzer.semver:semver to v2
  • Update dependency prism-react-renderer to v2
  • Update docusaurus monorepo to v3 (major) (@docusaurus/core, @docusaurus/plugin-content-docs, @docusaurus/plugin-content-pages, @docusaurus/preset-classic, @docusaurus/theme-classic)
  • Update gradle/wrapper-validation-action action to v3
  • Update kotlin monorepo to v2 (major) (org.jetbrains.kotlin.jvm, org.jetbrains.kotlin:kotlin-test, org.jetbrains.kotlin:kotlin-test-common, org.jetbrains.kotlin:kotlin-stdlib-jdk8, org.jetbrains.kotlin:kotlin-reflect, org.jetbrains.kotlin:kotlin-gradle-plugin-api, org.jetbrains.kotlin:kotlin-gradle-plugin, org.jetbrains.kotlin:kotlin-compiler-embeddable, org.jetbrains.kotlin:kotlin-annotation-processing-embeddable)
  • Update ktlint.gradle to v12 (major) (org.jlleitschuh.gradle.ktlint, org.jlleitschuh.gradle:ktlint-gradle)
  • Update mikepenz/action-junit-report action to v4
  • Update release-drafter/release-drafter action to v6
  • Update stefanzweifel/git-auto-commit-action action to v5
  • ๐Ÿ” Create all rate-limited PRs at once ๐Ÿ”

Warning

Renovate failed to look up the following dependencies: Failed to look up maven package kotlinx-knit:kotlinx-knit.gradle.plugin.

Files affected: gradle/libs.versions.toml


Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

Ignored or Blocked

These are blocked by an existing closed PR and will not be recreated unless you click a checkbox below.

Detected dependencies

github-actions
.github/workflows/ci.yml
  • styfle/cancel-workflow-action 0.10.0
  • actions/checkout v3
  • actions/setup-java v3
  • gradle/gradle-build-action v2
  • actions/checkout v3
  • actions/checkout v3
  • actions/setup-java v3
  • gradle/gradle-build-action v2
  • stefanzweifel/git-auto-commit-action v4
  • gradle/gradle-build-action v2
  • actions/checkout v3
  • actions/checkout v3
  • actions/setup-java v3
  • gradle/gradle-build-action v2
  • gradle/gradle-build-action v2
  • gradle/gradle-build-action v2
  • stefanzweifel/git-auto-commit-action v4
  • gradle/gradle-build-action v2
  • gradle/gradle-build-action v2
  • stefanzweifel/git-auto-commit-action v4
  • actions/checkout v3
  • actions/setup-java v3
  • gradle/gradle-build-action v2
  • actions/checkout v3
  • actions/checkout v3
  • actions/setup-java v3
  • gradle/gradle-build-action v2
  • stefanzweifel/git-auto-commit-action v4
  • gradle/gradle-build-action v2
  • actions/checkout v3
  • actions/setup-java v3
  • gradle/gradle-build-action v2
  • actions/checkout v3
  • actions/setup-node v3
  • gradle/wrapper-validation-action v1
  • actions/setup-java v3
  • gradle/gradle-build-action v2
  • gradle/gradle-build-action v2
  • gradle/gradle-build-action v2
  • gradle/gradle-build-action v2
  • actions/checkout v3
  • actions/setup-java v3
  • gradle/gradle-build-action v2
  • actions/upload-artifact v3
  • mikepenz/action-junit-report v3
  • actions/checkout v3
  • actions/setup-java v3
  • gradle/gradle-build-action v2
.github/workflows/publish-snapshot.yml
  • actions/checkout v3
  • actions/setup-java v3
  • gradle/gradle-build-action v2
  • gradle/gradle-build-action v2
  • gradle/gradle-build-action v2
.github/workflows/rebase.yml
  • cirrus-actions/rebase 1.7
.github/workflows/release-drafter.yml
  • release-drafter/release-drafter v5
.github/workflows/website.yml
  • actions/checkout v3
  • actions/setup-node v3
  • actions/setup-java v3
  • gradle/gradle-build-action v2
  • gradle/gradle-build-action v2
  • gradle/gradle-build-action v2
  • crazy-max/ghaction-github-pages v3
gradle
buildSrc/src/main/kotlin/Common.kt
buildSrc/src/main/kotlin/CommonAndroid.kt
buildSrc/src/main/kotlin/catalogs.kt
gradle.properties
settings.gradle.kts
  • com.gradle.enterprise 3.10
build.gradle.kts
buildSrc/settings.gradle.kts
buildSrc/build.gradle.kts
buildSrc/src/main/kotlin/androidLibrary.gradle.kts
buildSrc/src/main/kotlin/dependency-guard.gradle.kts
buildSrc/src/main/kotlin/detekt.gradle.kts
buildSrc/src/main/kotlin/dokka.gradle.kts
buildSrc/src/main/kotlin/javaLibrary.gradle.kts
buildSrc/src/main/kotlin/knit.gradle.kts
buildSrc/src/main/kotlin/published.gradle.kts
buildSrc/src/main/kotlin/website.gradle.kts
dispatch-android-espresso/gradle.properties
dispatch-android-espresso/build.gradle.kts
dispatch-android-lifecycle/gradle.properties
dispatch-android-lifecycle/build.gradle.kts
dispatch-android-lifecycle-extensions/gradle.properties
dispatch-android-lifecycle-extensions/build.gradle.kts
dispatch-android-viewmodel/gradle.properties
dispatch-android-viewmodel/build.gradle.kts
dispatch-bom/gradle.properties
dispatch-bom/build.gradle.kts
dispatch-core/gradle.properties
dispatch-core/build.gradle.kts
dispatch-detekt/gradle.properties
dispatch-detekt/build.gradle.kts
dispatch-internal-test/build.gradle.kts
dispatch-internal-test-android/build.gradle.kts
dispatch-sample/build.gradle.kts
dispatch-test/gradle.properties
dispatch-test/build.gradle.kts
dispatch-test-junit4/gradle.properties
dispatch-test-junit4/build.gradle.kts
dispatch-test-junit5/gradle.properties
dispatch-test-junit5/build.gradle.kts
gradle/libs.versions.toml
  • com.android.tools.build:gradle 7.2.2
  • androidx.activity:activity-compose 1.5.1
  • androidx.activity:activity 1.5.1
  • androidx.activity:activity-ktx 1.5.1
  • androidx.annotation:annotation 1.4.0
  • androidx.appcompat:appcompat 1.5.0
  • androidx.arch.core:core-testing 2.1.0
  • androidx.cardview:cardview 1.0.0
  • androidx.compose.compiler:compiler 1.3.0
  • androidx.compose.foundation:foundation 1.3.0
  • androidx.compose.material:material 1.3.0
  • androidx.compose.material:material-icons-core 1.3.0
  • androidx.compose.material:material-icons-extended 1.3.0
  • androidx.compose.runtime:runtime 1.3.0
  • androidx.compose.ui:ui-test-junit4 1.3.0
  • androidx.compose.ui:ui-test-manifest 1.3.0
  • androidx.compose.ui:ui 1.3.0
  • androidx.compose.ui:ui-tooling 1.3.0
  • androidx.constraintlayout:constraintlayout 2.1.4
  • androidx.core:core-ktx 1.8.0
  • androidx.exifinterface:exifinterface 1.3.3
  • androidx.fragment:fragment 1.5.2
  • androidx.fragment:fragment-ktx 1.5.2
  • androidx.fragment:fragment-testing 1.5.2
  • androidx.legacy:legacy-support-v13 1.0.0
  • androidx.lifecycle:lifecycle-common 2.5.1
  • androidx.lifecycle:lifecycle-extensions 2.5.1
  • androidx.lifecycle:lifecycle-livedata-core 2.5.1
  • androidx.lifecycle:lifecycle-livedata-ktx 2.5.1
  • androidx.lifecycle:lifecycle-process 2.5.1
  • androidx.lifecycle:lifecycle-runtime 2.5.1
  • androidx.lifecycle:lifecycle-runtime-ktx 2.5.1
  • androidx.lifecycle:lifecycle-viewmodel-compose 2.5.1
  • androidx.lifecycle:lifecycle-viewmodel 2.5.1
  • androidx.lifecycle:lifecycle-viewmodel-ktx 2.5.1
  • androidx.lifecycle:lifecycle-viewmodel-savedstate 2.5.1
  • androidx.multidex:multidex 2.0.1
  • androidx.navigation:navigation-common 2.5.1
  • androidx.navigation:navigation-compose 2.5.1
  • androidx.navigation:navigation-fragment-ktx 2.5.1
  • androidx.navigation:navigation-runtime-ktx 2.5.1
  • androidx.navigation:navigation-ui-ktx 2.5.1
  • androidx.paging:paging-runtime-ktx 3.1.1
  • androidx.paging:paging-common 3.1.1
  • androidx.paging:paging-compose 1.0.0-alpha15
  • androidx.paging:paging-common-ktx 3.1.1
  • androidx.paging:paging-runtime 3.1.1
  • androidx.percentlayout:percentlayout 1.0.0
  • androidx.recyclerview:recyclerview 1.2.1
  • androidx.room:room-common 2.4.3
  • androidx.room:room-compiler 2.4.3
  • androidx.room:room-ktx 2.4.3
  • androidx.room:room-paging 2.4.3
  • androidx.room:room-runtime 2.4.3
  • androidx.room:room-testing 2.4.3
  • androidx.savedstate:savedstate 1.2.0
  • androidx.security:security-crypto 1.0.0
  • androidx.startup:startup-runtime 1.1.1
  • androidx.test:core 1.4.0
  • androidx.test.ext:junit 1.1.3
  • androidx.test:orchestrator 1.4.1
  • androidx.test:rules 1.4.0
  • androidx.test:runner 1.4.0
  • androidx.test.ext:truth 1.4.0
  • androidx.test.espresso:espresso-contrib 3.4.0
  • androidx.test.espresso:espresso-core 3.4.0
  • androidx.test.espresso:espresso-idling-resource 3.4.0
  • androidx.test.espresso:espresso-intents 3.4.0
  • androidx.test.espresso:espresso-web 3.4.0
  • androidx.test.uiautomator:uiautomator 2.2.0
  • androidx.viewpager2:viewpager2 1.0.0
  • androidx.work:work-runtime 2.7.1
  • androidx.work:work-runtime-ktx 2.7.1
  • androidx.work:work-testing 2.7.1
  • app.cash.turbine:turbine 0.9.0
  • org.codehaus.groovy:groovy 3.0.12
  • org.codehaus.groovy:groovy-xml 3.0.12
  • io.coil-kt:coil-compose 2.2.1
  • io.coil-kt:coil 2.2.1
  • io.coil-kt:coil-gif 2.2.1
  • commons-io:commons-io 2.11.0
  • io.gitlab.arturbosch.detekt:detekt-api 1.21.0
  • io.gitlab.arturbosch.detekt:detekt-cli 1.21.0
  • io.gitlab.arturbosch.detekt:detekt-gradle-plugin 1.21.0
  • io.gitlab.arturbosch.detekt:detekt-test 1.21.0
  • io.gitlab.arturbosch.detekt:detekt-test-utils 1.21.0
  • com.dipien:bye-bye-jetifier 1.2.2
  • org.jetbrains.dokka:dokka-gradle-plugin 1.6.10
  • com.dropbox.dependency-guard:dependency-guard 0.3.1
  • com.google.accompanist:accompanist-coil 0.15.0
  • com.google.auto:auto-common 1.2.1
  • com.google.auto.service:auto-service-annotations 1.0.1
  • com.google.auto.service:auto-service 1.0.1
  • com.google.code.findbugs:jsr305 3.0.2
  • com.google.dagger:dagger 2.43.2
  • com.google.dagger:dagger-compiler 2.43.2
  • com.google.devtools.ksp:symbol-processing-gradle-plugin 1.7.10-1.0.6
  • com.google.android.material:material 1.6.1
  • com.google.truth:truth 1.1.3
  • com.rickbusarow.hermit:hermit-core 0.9.6
  • com.rickbusarow.hermit:hermit-coroutines 0.9.6
  • com.rickbusarow.hermit:hermit-junit4 0.9.6
  • com.rickbusarow.hermit:hermit-junit5 0.9.6
  • com.rickbusarow.hermit:hermit-mockk 0.9.6
  • org.junit.jupiter:junit-jupiter-api 5.9.0
  • org.junit.jupiter:junit-jupiter-engine 5.9.0
  • org.junit.jupiter:junit-jupiter 5.9.0
  • org.junit.jupiter:junit-jupiter-params 5.9.0
  • junit:junit 4.13.2
  • org.junit.vintage:junit-vintage-engine 5.9.0
  • io.kotest:kotest-assertions-core-jvm 5.4.2
  • io.kotest:kotest-assertions-shared-jvm 5.4.2
  • io.kotest:kotest-common-jvm 5.4.2
  • io.kotest:kotest-property-jvm 5.4.2
  • io.kotest:kotest-runner-junit5-jvm 5.4.2
  • org.jetbrains.kotlin:kotlin-annotation-processing-embeddable 1.7.10
  • org.jetbrains.kotlin:kotlin-compiler-embeddable 1.7.10
  • org.jetbrains.kotlin:kotlin-gradle-plugin 1.7.10
  • org.jetbrains.kotlin:kotlin-gradle-plugin-api 1.7.10
  • org.jetbrains.kotlin:kotlin-reflect 1.7.10
  • org.jetbrains.kotlin:kotlin-stdlib-jdk8 1.7.10
  • org.jetbrains.kotlin:kotlin-test-common 1.7.10
  • org.jetbrains.kotlin:kotlin-test 1.7.10
  • com.github.tschuchortdev:kotlin-compile-testing 1.4.9
  • org.jetbrains.kotlinx:atomicfu-gradle-plugin 0.18.3
  • org.jetbrains.kotlinx:kotlinx-coroutines-android 1.5.2
  • org.jetbrains.kotlinx:kotlinx-coroutines-core 1.5.2
  • org.jetbrains.kotlinx:kotlinx-coroutines-core-common 1.5.2
  • org.jetbrains.kotlinx:kotlinx-coroutines-jdk8 1.5.2
  • org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm 1.5.2
  • org.jetbrains.kotlinx:kotlinx-coroutines-play-services 1.5.2
  • org.jetbrains.kotlinx:kotlinx-coroutines-test 1.5.2
  • org.jetbrains.kotlinx:kotlinx-metadata-jvm 0.5.0
  • org.jetbrains.kotlinx:kotlinx-knit 0.4.0
  • org.jetbrains.kotlinx:kotlinx-knit-test 0.4.0
  • org.jlleitschuh.gradle:ktlint-gradle 11.0.0
  • io.mockk:mockk 1.12.7
  • org.objenesis:objenesis 3.3
  • org.robolectric:robolectric 4.8.2
  • gradle.plugin.dev.arunkumar:scabbard-gradle-plugin 0.5.0
  • com.squareup.anvil:annotations 2.4.2
  • com.squareup.anvil:compiler-api 2.4.2
  • com.squareup.anvil:compiler 2.4.2
  • com.squareup.anvil:compiler-utils 2.4.2
  • com.squareup.anvil:gradle-plugin 2.4.2
  • com.squareup.moshi:moshi-adapters 1.13.0
  • com.squareup.moshi:moshi 1.13.0
  • com.squareup.moshi:moshi-kotlin 1.13.0
  • com.squareup.moshi:moshi-kotlin-codegen 1.13.0
  • com.squareup.okhttp3:okhttp 4.10.0
  • com.squareup.okhttp3:logging-interceptor 4.10.0
  • com.squareup.okhttp3:mockwebserver 4.10.0
  • com.squareup.retrofit2:retrofit 2.9.0
  • com.squareup.retrofit2:retrofit-mock 2.9.0
  • com.squareup.retrofit2:converter-moshi 2.9.0
  • com.squareup.okio:okio 3.2.0
  • com.squareup.okio:okio-bom 3.2.0
  • com.squareup.picasso:picasso 2.71828
  • net.swiftzer.semver:semver 1.2.0
  • com.jakewharton.timber:timber 5.0.1
  • com.vanniktech:gradle-maven-publish-plugin 0.22.0
  • dev.zacsweers.autoservice:auto-service-ksp 1.0.0
  • dev.zacsweers.moshix:moshi-ksp 0.18.3
  • dev.zacsweers.moshix:moshi-sealed-runtime 0.18.3
  • dev.zacsweers.moshix:moshi-sealed-codegen 0.18.3
  • dev.zacsweers.moshix:moshi-sealed-ksp 0.18.3
  • com.squareup.anvil 2.4.2
  • com.github.ben-manes.versions 0.42.0
  • com.autonomousapps.dependency-analysis 1.13.1
  • io.gitlab.arturbosch.detekt 1.21.0
  • com.dropbox.dependency-guard 0.3.1
  • com.osacky.doctor 0.8.1
  • org.jetbrains.kotlin.jvm 1.7.10
  • org.jlleitschuh.gradle.ktlint 11.0.0
  • com.dorongold.task-tree 2.1.0
  • com.rickbusarow.gradle-dependency-sync 0.11.4
  • com.rickbusarow.module-check 0.12.3
  • org.jetbrains.dokka 1.6.10
  • org.jetbrains.kotlinx.binary-compatibility-validator 0.11.1
  • kotlinx-knit 0.4.0
gradle-wrapper
gradle/wrapper/gradle-wrapper.properties
  • gradle 7.5.1
npm
website/package.json
  • @babel/core 7.19.1
  • @babel/helper-compilation-targets 7.19.1
  • @docusaurus/core 2.1.0
  • @docusaurus/plugin-content-docs 2.1.0
  • @docusaurus/plugin-content-pages 2.1.0
  • @docusaurus/preset-classic 2.1.0
  • @docusaurus/theme-classic 2.1.0
  • @mdx-js/react 1.6.22
  • clsx 1.2.1
  • mdx-mermaid 1.3.2
  • mermaid 9.1.7
  • prism-react-renderer 1.3.5
  • react 18.2.0
  • react-dom 18.2.0
  • react-infima 0.0.1-alpha.4

  • Check this box to trigger a request for Renovate to run again on this repository

Make testProvided's lambda extend TestProvidedCoroutineScope

Currently testProvided's lambda receives a TestCoroutineScope. This gives the extra functionality from TestCoroutineDispatcher. TestProvidedCoroutineScope implements TestCoroutineScope.

TestProvidedCoroutineScope doesn't offer any new functionality by way of properties or functions, and the benefits from DispatcherProvider don't require that it's declared as any specific type. So there are two benefits of receiving a TestProvidedCoroutineScope over an ordinary TestCoroutineScope:

  1. The Dispatch version implements all specific CoroutineScope types, so it can be used as an argument regardless of the parameter type.
  2. Any future addition to the scope's API would then require this change, so doing it now is future-proofing.

CoroutineTestExtension does not always use Dispatchers.setMain()

Any time the extension injects a new scope via constructor or function argument, it puts that scope into a MutableMap where the key its the ExtensionContext. This map is used in beforeEach to call setMain(...) and in afterEach to call resetMain() and cleanUpTestCoroutines().

This is the existing beforeEach:

  override fun beforeEach(context: ExtensionContext) {
    contextScopeMap[context]?.dispatcherProvider?.main?.let {
      Dispatchers.setMain(it)
    }
  }

Here's a simplified timeline of a JUnit5 test execution with parameter resolution:

  1. Initialize extension (no context here for the internal scope property).
  2. Create constructor dependencies and add to map.
  3. Create class.
  4. beforeEach()
  5. Create function dependencies and add to map.
  6. Execute test function with parameters.
  7. afterEach()

Dispatchers.setMain(...) works with constructor parameters because they've been added to the map before beforeEach() is invoked. It doesn't work with the internal scope property because it's never added to the map. It also doesn't work for injected function parameters because they're constructed and added to the map after beforeEach() is invoked.

Kotlin Multiplatform support

Hi!
Does dispatch-core support Kotlin Native? How I can use it in commonMain?
Or KN support will be in future?

Missing license URL

Hi!

We've encountered a small nuisance in the Maven configuration of this library. The license URL tag

<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>

is missing from the generated POM files for artifacts of this project. This makes it impossible for some 3rd party tools like https://github.com/jaredsburrows/gradle-license-plugin/ to automatically display the correct license of this library.

Many thanks for your work!

AndroidX capitalization

AndroidX uses a capitalized 'X', but the project has lots of places where it's "Androidx".

Introduce LifecycleCoroutineScopeFactory

If using LifecycleCoroutineScope but not using the lifecycleScope extension, the current best option for providing a custom scope/context via DI like Dagger may look like this:

class SomeFragment @Inject constructor(
  coroutineScope: MainImmediateCoroutineScope
) : Fragment() {

  private val lifecycleScope = LifecycleCoroutineScope(this, coroutineScope)

  // ...
}

This isn't terrible, since everything important is in the injected scope, but it can be improved.

class SomeFragment @Inject constructor(
  lifecycleCoroutineScopeFactory: LifecycleCoroutineScopeFactory
) : Fragment() {

  private val lifecycleScope = lifecycleCoroutineScopeFactory.create(this)

  // ...
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.