airbnb / DeepLinkDispatch

A simple, annotation-based library for making deep link handling better on Android
http://nerds.airbnb.com/deeplinkdispatch/
4.38k stars 405 forks source link

Support dynamic feature modules #255

Closed MohamedElidrissi closed 5 years ago

MohamedElidrissi commented 5 years ago

Currently there's no way to use DeepLinkDispatch in a modularized Android project where we have multiple feature modules since if we have our @DeepLinkHandler Activity in the base module and we want to add a @DeepLinkModule annotated class that resides in a feature module we can't as the base module doesn't depend on the feature modules. if there is a workaround for this feel free to close this issue

MohamedElidrissi commented 5 years ago

Since nobody seems to care about this, I dug into DLD and I found a way to workaround this by making a CustomDeepLinkDelegate class that accepts a List<? extends Parser> directly, this makes it possible do use dependency injection to pass a List of *DeepLinkLoader classes instead of depending on the generated DeepLinkDelegate that forces the use of the @DeepLinkHandler thus making it impossible to add loaders dynamically (I'm yet to test this with feature modules, hopefully it works well 🤞)

MohamedElidrissi commented 5 years ago

After trying out the above it does work fine, however looking at all the boilerplate and reflection I'm not sure I'll do this in a production app Annotation 2019-06-07 174529

Annotation 2019-06-07 174735

leanh215 commented 5 years ago

Basically use reflection to get Loader and add to a BaseDeepLinkDelegate is OK. I tested with below code and it worked well


class DeepLinkActivity : Activity() {

    companion object {
        const val DYNAMIC_DEEPLINK_LOADER = "com.xxx.dynamicfeature.deeplink.DynamicDeepLinkModuleLoader"
        const val DYNAMIC_DEEPLINK_LOADER_NOT_EXIST = "com.xxx.dynamicfeature.deeplink.DynamicDeepLinkModuleLoaderXXX"
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val delegate = BaseDeepLinkDelegate(
            listOfNotNull(
                AppDeepLinkModuleLoader(),
                loadDeepLinkLoader(DYNAMIC_DEEPLINK_LOADER),
                loadDeepLinkLoader(DYNAMIC_DEEPLINK_LOADER_NOT_EXIST)
            )
        )
        delegate.dispatchFrom(this)
        finish()
    }

    private fun loadDeepLinkLoader(loadClassName: String): Parser? {
        return try {
            Class.forName(loadClassName).newInstance() as Parser
        } catch (e: Exception) {
            e.printStackTrace()
            null
        }
    }
}