简体   繁体   English

如何使用泛型或反射来显示/隐藏片段? Kotlin Android

[英]How to use Generics or Reflection to show/hide fragments? Kotlin Android

I have a fragment manager to show/hide fragments in my app. 我有一个片段管理器来显示/隐藏我的应用程序中的片段。 Right now when I want to show a fragment from any activity or fragment I call this method from the manager 现在,当我想显示任何活动或片段的片段时,请从管理器中调用此方法

 fun show(manager: FragmentManager, fragmentTag: String, container: Int, data: Any?): Companion {
        var fragment = manager.findFragmentByTag(fragmentTag)
        if (fragment != null) {
            manager.popBackStack(fragmentTag, 0)
        } else {
            addFragment(manager, getFragment(fragmentTag, manager, data)!!, container, fragmentTag)
        }
        return this
    }

 private fun getFragment(fragmentTag: String, manager: FragmentManager, data: Any?): Fragment? {
        when (fragmentTag) {
            MenuFragment.TAG -> return getMenuFragment(manager)
            TagsFragment.TAG -> return getTagsFragment(manager)
            ...
        }
        return null
    }

with return a fragment with a specific class 与返回具有特定类的片段

private fun getMenuFragment(manager: FragmentManager): Fragment {
        var fragment = manager.findFragmentByTag(MenuFragment.TAG) as MenuFragment?
        if (fragment == null) {
            fragment = MenuFragment.newInstance()
        }
        return fragment
    }

I would like to have an strategy to avoid create one method every time I need to implement a new fragment, so I was thinking about generics or maybe reflection wich I have never used before. 我想有一个策略来避免每次需要实现一个新片段时都创建一个方法,所以我在考虑泛型或也许从未使用过的反射。

Is there any way to do this using reflection? 有什么办法可以使用反射来做到这一点? or another better strategy? 还是另一个更好的策略?

Thanks for any help. 谢谢你的帮助。

Edit 编辑

As I have one Activity and many fragments I finally extended FragmentManager to use it in every fragment. 由于我有一个Activity和许多片段,因此我最终扩展了FragmentManager以在每个片段中使用它。

inline fun <reified T : Fragment> FragmentManager.showFragment(tag: String, container: Int, args: Bundle? = null) {
    val clazz = T::class.java
    var fragment = findFragmentByTag(clazz.name)
    if (fragment != null) {
        this.popBackStack(tag, 0)
    } else {
        fragment = (clazz.getConstructor().newInstance() as T).apply {
            args?.let {
                it.classLoader = javaClass.classLoader
                arguments = args
            }
        }
        val transaction = this.beginTransaction()
        transaction.add(container, fragment as Fragment, tag)
        transaction.addToBackStack(tag)
        transaction.commit()
    }
}

call: 呼叫:

 activity!!.supportFragmentManager.showFragment<MenuFragment>(MenuFragment.TAG, R.id.container)

With Reflection provided that the fragment tag is the fully qualified name of the class provided using MenuFragment::class.java.name 通过Reflection提供的条件是,fragment标签是使用MenuFragment::class.java.name提供的类的完全限定名称。

private fun getFragment(fragmentTag: String, manager: FragmentManager, data: Any?): Fragment? {
    return manager.findFragmentByTag(fragmentTag) ?: getFragment(fragmentTag)
}

private fun getFragment(fragmentTag: String): Fragment? {
    val c = Class.forName(fragmentTag)
    return c.getMethod("newInstance").invoke(null) as Fragment?
}

Without Reflection 没有反思

private fun getFragment(fragmentTag: String, manager: FragmentManager, data: Any?): Fragment? {
    return manager.findFragmentByTag(fragmentTag) ?: when (fragmentTag) {
        MenuFragment.TAG -> MenuFragment.newInstance()
        TagsFragment.TAG -> TagsFragment.newInstance()
        else -> null
    }
}

if I correctly understood a question, you can write extension function for FragmentManager like this 如果我正确理解了一个问题,可以像这样为FragmentManager编写扩展功能

inline fun <reified T : Fragment> FragmentManager.getFragment(args: Bundle? = null): Fragment {
    val clazz = T::class.java
    return findFragmentByTag(clazz.name) ?: return (clazz.getConstructor().newInstance() as T).apply {
        args?.let { 
            it.classLoader = javaClass.classLoader
            arguments = args
        }
    }
}

end then use it, eg in activity 然后在活动中使用它

val frag = supportFragmentManager.getFragment<MyFragment>()

where MyFragment - is your fragment class MyFragment-是您的片段类

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM