Как узнать, принадлежат ли два ArrayList от одного типа - PullRequest
0 голосов
/ 03 июля 2019

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

Цель

Поскольку это 7фрагменты хранят данные в различных типах ArrayLists. Я создал общий класс ViewModel, чтобы передать эти данные моей основной операции (держателю фрагментов)

SharedViewModel

class SharedViewModel<T>: ViewModel() {

    var data:MutableLiveData<ArrayList<T>> = MutableLiveData()

    fun setData(anyData:ArrayList<T>){
        data.value = anyData
    }

    val getAnyData:LiveData<ArrayList<T>>
    get() = data

}

Делая это, я просто устанавливаю любой массивтип данных внутри каждого фрагмента

  (activity as MainActivity).getViewModelInstance().setData(xArray)

И в моей MainActivity я хочу проверить, является ли этот тип данных xArray того же типа, что и тот, который объявлен глобально в MainActivity, если они равны, это должно учитывать текущие данные массивазначения для нового пустого массива

MainActivity

private var xArray = arrayListOf<Xclass>()

    onCreate()
    ...

     viewModel = ViewModelProviders.of(this).get(SharedViewModel::class.java)
            viewModel.getAnyData.observe(this, Observer { it:ArrayList<out Any?>
                if(it == xArray){
                    xArray.addAll(it)
                }
            })

Цель

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

Проблемы

Есть две проблемы

  • Первая, как уже упоминалось, заключается в том, как сравнить текущий массив ArrayList, полученный наблюдателем в моей MainActivity, с массивомчто я объявил.Они должны проверить, являются ли оба it и xArray ArrayLists одного типа
  • Вторая ошибка - это

    (активностькак MainActivity) .getViewModelInstance (). setData (xArray)

В .setData(xArray) выделен красным высказыванием Required: Nothing, Found:ArrayList<Xclass>.Это странно, потому что setData SharedViewModel требует передачи любого ArrayList.

Спасибо

1 Ответ

1 голос
/ 04 июля 2019

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

class SharedViewModel <T> (val listType: Class<T>) : ViewModel() {

    var data: MutableLiveData<ArrayList<T>> = MutableLiveData()

    fun setData(anyData: ArrayList<T>) {

        data.value = anyData
    }

    inline fun <reified K> isOfInternalType(checkType: Class<K>): Boolean = checkType.typeName == listType.typeName
}

Установка данных массива через viewModel

class Xclass
var xArray = arrayListOf<Xclass>()

val viewModel = (activity as MainActivity).getViewModelInstance()
if (viewModel.isOfInternalType(Xclass::class.java) {
    viewModel.setData(Xclass)
}

Основная активность

class Xclass
private var xArray = arrayListOf<Xclass>()

onCreate()
...

viewModel = ViewModelProviders.of(this).get(SharedViewModel::class.java)
viewModel.getAnyData.observe(this, Observer { data: ArrayList<out Any?> ->
    if (viewModel.isOfInternalType(Xclass::class.java) {
        xArray.addAll(it)
    }
})

Другие примеры использования

// Examples of use cases outside of initial question

class ViewOne: SharedView<ClassOne>(ClassOne::class.java)
val testClass = ViewOne()

ViewOne().isOfInternalType(ClassTwo::class.java) // returns false
ViewOne().isOfInternalType(testClass::class.java) // Error: Cannot use captured type as reified parameter

ViewOne().isOfInternalType(ClassOne::class.java) // returns true
ViewOne().isOfInternalType(ClassOne().javaClass) // returns true
testClass.isOfInternalType(ClassOne::class.java) // returns true

То, что я сделал, - это создание экземпляра listType представления, ожидаемого при создании экземпляра.Это необходимо сделать, потому что классы не поддерживают преобразование типов, как встроенная функция.В этой реализации предполагается, что каждый View будет иметь статический listType ... Это можно изменить, чтобы он выглядел следующим образом:

class SharedViewModel(listType: Class<*>) : ViewModel() {
    var listType: Class<*> = listType
    private set(value) {
        field = value
    }

    fun setData(anyData: ArrayList<*>) {
        data.value = anyData
    }

    fun updateListType(newType: Class<*>) {
        listType = newType
    }

    inline fun <reified K> isOfInternalType(checkType: Class<K>): Boolean =
        checkType.typeName == listType.typeName
}

Тип переменной SharedViewModel Примеры

class ViewOne: SharedView(ClassOne::class.java)

val testClass = ViewOne()

testClass.isOfInternalType(ClassOne::class.java) // returns true

testClass.updateListType(ClassTwo::class.java)

testClass.isOfInternalType(ClassOne::class.java)  // returns false now
testClass.isOfInternalType(ClassTwo::class.java)  // returns true now

С помощью этой реализации переменнойнабирая текст, вы захотите связать свой isOfInternalType с setData, чтобы обеспечить безопасность типов

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

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