question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Scene cannot be cast to android.content.ComponentCallbacks

See original GitHub issue

在使用依赖注入框架 Koin 注入 ViewModel 时报 ClassCastException 异常,是否应该为 Scene 继承 ComponentCallbacks 接口https://github.com/bytedance/scene/blob/3dc15e1f2e5ce0acc662c65613475ee386341a24/library/scene/src/main/java/com/bytedance/scene/Scene.java#L112 image

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:6 (2 by maintainers)

github_iconTop GitHub Comments

12reactions
emredagcicommented, Jul 5, 2021

If you would like to use two frameworks together, you should define a new extension then you can use the koin framework with scene framework.


import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.*
import com.bytedance.scene.Scene
import org.koin.android.viewmodel.*
import org.koin.core.Koin
import org.koin.core.context.GlobalContext
import org.koin.core.parameter.ParametersDefinition
import org.koin.core.qualifier.Qualifier
import org.koin.core.scope.Scope
import kotlin.reflect.KClass

inline fun <reified T : ViewModel> LifecycleOwner.customViewModel(
    qualifier: Qualifier? = null,
    noinline parameters: ParametersDefinition? = null
): Lazy<T> = lazy { getViewModelCustom(qualifier, parameters) }

inline fun <reified T : ViewModel> LifecycleOwner.getViewModelCustom(
    qualifier: Qualifier? = null,
    noinline parameters: ParametersDefinition? = null
): T {
    return getViewModelCustom(T::class, qualifier, parameters)
}

fun <T : ViewModel> LifecycleOwner.getViewModelCustom(
    clazz: KClass<T>,
    qualifier: Qualifier? = null,
    parameters: ParametersDefinition? = null
): T {
    return GlobalContext.get().koin.getViewModelCustom(
        ViewModelParameters(
            clazz,
            this@getViewModelCustom,
            qualifier,
            parameters = parameters
        )
    )
}

fun <T : ViewModel> Koin.getViewModelCustom(parameters: ViewModelParameters<T>): T {
    val vmStore: ViewModelStore = parameters.owner.getViewModelStoreCustom(parameters)
    val viewModelProvider = rootScope.createViewModelProviderCustom(vmStore, parameters)
    return viewModelProvider.getInstanceCustom(parameters)
}

fun <T : ViewModel> ViewModelProvider.getInstanceCustom(parameters: ViewModelParameters<T>): T {
    val javaClass = parameters.clazz.java
    return if (parameters.qualifier != null) {
        this.get(parameters.qualifier.toString(), javaClass)
    } else {
        this.get(javaClass)
    }
}

fun <T : ViewModel> LifecycleOwner.getViewModelStoreCustom(
    parameters: ViewModelParameters<T>
): ViewModelStore =
    when {
        parameters.from != null -> parameters.from!!.invoke().viewModelStore
        this is FragmentActivity -> ViewModelStores.of(this)
        this is Fragment -> ViewModelStores.of(this)
        this is Scene -> this.viewModelStore
        else -> error("Can't getByClass ViewModel '${parameters.clazz}' on $this - Is not a FragmentActivity nor a Fragment neither a valid ViewModelStoreOwner")
    }

fun <T : ViewModel> Scope.createViewModelProviderCustom(
    vmStore: ViewModelStore,
    parameters: ViewModelParameters<T>
): ViewModelProvider {
    return ViewModelProvider(
        vmStore,
        object : ViewModelProvider.Factory {
            override fun <T : ViewModel> create(modelClass: Class<T>): T {
                return get(parameters.clazz, parameters.qualifier, parameters.parameters)
            }
        })
}

After you created the extension you can use like code shown below.

class SplashScene : Scene() {

    private val splashViewModel: SplashViewModel by customViewModel()

}
1reaction
Ccixyjcommented, Mar 30, 2020

另外一种是自己写一个LifecycleOwner.getKoin()的扩展方法。然后通过getkoin().getViewModel(lifecycleowner…)手动实现一个viewmodl代理方法。

fun LifecycleOwner.getKoin(): Koin = when (this) {
    is KoinComponent -> this.getKoin()
    is Scene -> ((this as? KoinComponent)?.getKoin()
        ?: (this.requireActivity() as? KoinComponent)?.getKoin()
        ?: error("scene attach parent must be KoinComponent"))
    else -> KoinContextHandler.get()
}
Read more comments on GitHub >

github_iconTop Results From Across the Web

android callback fails in fragment fails cannot be cast to ...
Here, you're trying to cast gpsu to a Context . It's is not one; it's a Fragment . You should pass the Context...
Read more >
ComponentCallbacks2 - Android Developers
Extended ComponentCallbacks interface with a new callback for finer-grained memory management. This interface is available in all application components ...
Read more >
BaseArFragment | Sceneform (1.15.0) - Google Developers
Called when a touch event is dispatched to a scene. void. onRequestPermissionsResult(int requestCode, String[] permissions, int[] results).
Read more >
core/java/android/app/Activity.java - platform/frameworks/base
activity on-screen, though it may not be in the foreground and interacting ... Retrieve the {@link Scene} representing this window's current content.
Read more >
ActivityGroup Class (Android.App) - Microsoft Learn
If this activity is being destroyed because it can not handle a configuration parameter ... Retrieve the Scene representing this window's current content....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found