Generi c способ обработки всех типов ответов во фрагменте - PullRequest
0 голосов
/ 02 августа 2020

Я создал класс Generi c Fragment для обработки всех типов ответов с сервера. Я хочу создать своего рода DataTableProvider <*> для обработки любого типа ответа.

Как я могу этого добиться.

class TestFragmentActivity : AppCompatActivity(), DataTableProvider<Any> {

    protected val mTabPatientsFragment = TabPatientsFragment()
    protected val mTabObservationsFragment = TabObservationsFragment()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_test_fragment)

        replaceFragment()

    }

    private fun replaceFragment(){
        supportFragmentManager.beginTransaction().replace(R.id.frame_container,
            mTabPatientsFragment).commit()
    }

    override fun getDataTableListener(mTableFragment: DataTableFragment<Any>): DataTableListener<Any> {
        val dataTableId = mTableFragment.dataTableId
        if (dataTableId.equals("observations"))
            return mTabObservationsFragment
        else return mTabPatientsFragment
    }

    override fun getDataTableConfig(mTableFragment: DataTableFragment<Any>): DataTableConfig {
        val dataTableId = mTableFragment.dataTableId
        val config = DataTableConfig()

        config.noRecordCell = R.layout.cell_no_record
        config.showSearch = false
        config.showAddButton = false

        if (dataTableId.equals("observations"))
        {
            config.cellResourceId = R.layout.home_observation_cell
        } else config.cellResourceId = R.layout.home_patient_cell

        return config
    }

}

getDataTableListener обратный вызов в приведенном выше фрагменте имеет ошибку требуется несоответствие типов DataTableListener обнаружен TabObservationFragment

TabObservationFragment

class TabObservationFragment : AppBaseFragment(),DataTableListener<Observation>

TabPatientFragment

class TabPatientFragment : AppBaseFragment(),DataTableListener<Patient>

Как я мог настроить его на работу для всех типов ответов.

Я пробовал DataTableListener <*> , но не смог добиться

Ошибка состояния

проекции не допускаются для непосредственных аргументов супертипа

Как я могу использовать DataTableProvider <*> для работы со всеми типами ответов

Edit

У меня есть пара фрагментов с fragmentViewpager внутри TestFragmentActivity.

У меня есть структура, которая помогает реализовать разбиение на страницы, поиск и реализацию всего во фрагменте. Но в соответствии с этой структурой DataTableProvider должен обрабатываться в активности и на основе tableId. Я обновил обратный вызов getDataTableListener и getDataTableListener

Вышеупомянутый обратный вызов должен возвращать некоторый тип

Есть ли способ выполнить обратный вызов, как показано ниже

override fun getDataTableConfig(mTableFragment: DataTableFragment<*>?): DataTableConfig?

override fun getDataTableListener(mTableFragment: DataTableFragment<*>?): DataTableListener<*>?

1 Ответ

0 голосов
/ 02 августа 2020

Быстрый ответ, используйте модификатор «out»:

fun getDataTableListener(mTableFragment: DataTableFragment<Any>): DataTableListener<out Any>

Длинный ответ:

То, что вы ищете, - это дисперсия, о которой вы можете прочитать в официальных kotlin документах: https://kotlinlang.org/docs/reference/generics.html

Потому что, например, интерфейс списка выглядит так:

public interface List<out E>

Вы можете выполнить задание следующим образом:

val list: List<Any> = listOf(1,2,3)

Но это невозможно сделать:

val mutableList : MutableList<Any> = listOf(1,2,3)

Потому что MutableList не имеет модификатора "out". Это имеет смысл, поскольку MutableList можно изменить, на MutableList вы можете добавить, например, String, но он уже указывает на List.

В вашем примере вы можете использовать модификатор «out», если и только если ваш DataTableListener не использует тип generi c в качестве входных данных. Например:

interface DataTableListener<T>{
    fun assignValue(t:T)
    fun getValue():T
}

С интерфейсом, подобным описанному выше, вы все равно можете использовать модификатор out в своей функции, но не сможете выполнить функцию assignValue.

Whole например:

class Patient
class Observation

class DataTableFragment<T>
interface DataTableListener<T> {
    fun assignValue(t: T)
    fun getValue(): T
}

class TabObservationFragment : DataTableListener<Observation> {
    override fun getValue(): Observation {
        TODO("Not yet implemented")
    }

    override fun assignValue(t: Observation) {
        TODO("Not yet implemented")
    }
}

class TabPatientFragment : DataTableListener<Patient> {
    override fun getValue(): Patient {
    }

    override fun assignValue(t: Patient) {
        TODO("Not yet implemented")
    }
}

val mTabObservationsFragment = TabObservationFragment()
val mTabPatientsFragment = TabPatientFragment()

fun getDataTableListener(mTableFragment: DataTableFragment<Any>): DataTableListener<out Any> {
    val test = "observations"
    if (test == "observations")
        return mTabObservationsFragment
    else return mTabPatientsFragment
}

fun getIt() {
    val listener = getDataTableListener(DataTableFragment())
    listener.assignValue("test")
}
...