Как использовать Generics или Reflection, чтобы показать / скрыть фрагменты?Котлин Android - PullRequest
1 голос
/ 21 марта 2019

У меня есть менеджер фрагментов для отображения / скрытия фрагментов в моем приложении. Прямо сейчас, когда я хочу показать фрагмент из любого действия или фрагмента, я вызываю этот метод из менеджера

 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
    }

с возвратом фрагмента определенного класса

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

Мне бы хотелось иметь стратегию, позволяющую избегать создания одного метода каждый раз, когда мне нужно реализовать новый фрагмент, поэтому я думал о дженериках или, возможно, об отражении, которое я никогда раньше не использовал.

Есть ли способ сделать это с помощью отражения? или другая лучшая стратегия?

Спасибо за любую помощь.

Редактировать

Поскольку у меня есть одно действие и много фрагментов, я наконец расширил 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()
    }
}

звоните:

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

Ответы [ 2 ]

2 голосов
/ 21 марта 2019

С Reflection при условии, что тег фрагмента является полностью определенным именем класса, предоставленным с использованием 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?
}

Без отражения

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
    }
}
1 голос
/ 22 марта 2019

если я правильно понял вопрос, вы можете написать функцию расширения для 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
        }
    }
}

конец, затем используйте его, например, в деятельности

val frag = supportFragmentManager.getFragment<MyFragment>()

где MyFragment - ваш класс фрагмента

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...