ArrayList автоматически дублирует элементы в нем

#android #kotlin #arraylist #android-viewpager2

#Android #котлин #список объектов #android-страница просмотра 2

Вопрос:

Я создал переменную private var deals=ArrayListlt;Dealsgt;() в a fragment и установил прослушиватель щелчков onCerateView() , как показано ниже.

 binding.tvAllDeals.setOnClickListener {  viewAllDeals()  }  

Так что это вызовет следующий метод

 private fun viewAllDeals(){  val intent = Intent(context,ViewAllDealsActivity::class.java)  intent.putExtra("details",deals)  Log.d("Tag2", "Size is ${deals.size}")  startActivity(intent)  }  

У меня есть следующая функция для получения данных из firestore , а затем я сохраняю результат в переменной «сделки». Однако всякий раз, когда я нажимаю «tvAllDeals», он показывает много изображений, когда я проверяю размер «сделок» с помощью Log.d «Tag1», всегда отображается правильный размер, равный 3, тогда как «Tag2» показывает некоторые случайные числа, такие как 6, 9, 24. Я пытаюсь выяснить, почему это происходит, но у меня не было ни малейшего представления. Переменная «deals» не используется нигде, кроме объявления и инициализации, для присвоения значения и передачи его в » viewAllDeals ()».

 private fun getDeals() {  FirestoreClass().getDeals(  onSuccess = { list -gt;  Result.success(list)  successDeals(list) ///// THIS FUNCTION WILL SHOW THE IMAGES IN A VIEWPAGER  deals.clear()  deals=list  Log.d("Tag1", "Size is ${deals.size}")  },  onFailure = {  }  ) }  

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

ПРИМЕЧАНИЕ: «Tag3» также показывает правильный размер массива, как «Tag1». Однако,

 private fun successDeals(list: ArrayListlt;Dealsgt;) {   Log.d("Tag3", "Size is ${deals.size}")   if (list.size gt; 0) {  binding.vpDeals.visibility = View.VISIBLE  val adapter = DealsAdapter(binding.vpDeals,requireContext(), list)  binding.vpDeals.adapter = adapter  binding.vpDeals.orientation = ViewPager2.ORIENTATION_HORIZONTAL   sliderHandle= Handler()  sliderRun= Runnable {  binding.vpDeals.currentItem=binding.vpDeals.currentItem 1  }   binding.vpDeals.registerOnPageChangeCallback(  object :ViewPager2.OnPageChangeCallback(){  override fun onPageSelected(position: Int) {  super.onPageSelected(position)   sliderHandle.removeCallbacks(sliderRun)  sliderHandle.postDelayed(sliderRun,4000)  }  }  )   } else {  binding.vpDeals.visibility = View.GONE  } }  

Комментарии:

1.Моя рекомендация-никогда не объединяться var с ArrayList или MutableList. Изменение его двумя различными способами усложняет работу с ним и затрудняет предотвращение ошибок. И если вы можете выбирать между а var List и а val MutableList , то var List это менее подвержено ошибкам. Это делает невозможным случайное изменение экземпляра списка, от которого зависит какой-либо другой класс, например ваш видоискатель, или забывание очистить список перед добавлением элементов и т. Д. (Возможно, причиной вашей проблемы может быть то, что вы где-то забыли очистить список.)

2. Можете ли вы показать successDeals функцию?

3. Я не вижу конкретно, что вызывает вашу проблему, но я вижу множество запахов кода. 1) Result.success(list) создает объект результата и ничего с ним не делает, поэтому эту строку следует удалить. 2) deals является одновременно a var и an ArrayList , поэтому он может изменяться двумя различными способами. 3) Вы очищаете список, на который ссылается, deals перед его переназначением. Поскольку вы передаете изменяемые списки, это может иметь неожиданные побочные эффекты, потому что кто знает, какие другие классы полагаются на этот список. Какой смысл его очищать? 4) successDeals требует конкретно списка типов ArrayList…

4. …без всякой причины, потому что он не мутирует и не делает ничего, требующего определенного поведения списка под капотом. 5) Создание обработчика внутри successDeals , поэтому каждый раз, когда он вызывается, старый обработчик теряется. Это очень подвержено ошибкам. Вы можете подумать, что ваш прослушиватель щелчков останавливает старую выполняемую программу, когда это не так, потому что он смотрит на другой обработчик, чем тот, который использовался ранее.

5. 6) Создание адаптера inisde successDeals . Адаптеры следует создавать и назначать только один раз (обычно в Activity.onCreate или Fragment.onViewCreated ), но это приведет к повторному созданию адаптера при каждом successDeals вызове, что приведет к потере всех ранее созданных представлений и исполняемых файлов.