Использовать элемент ViewHolder вне onBindViewHolder?

Можно ли использовать элемент ViewHolder вне onBindViewHolder?

Это мой класс адаптера

    @SuppressLint("SetTextI18n")
        override fun onBindViewHolder(holder: ViewHolder, position: Int) {
            val item = mValues[position]
            with(holder.mView) {
                tag = item
                txvTitle.text = item.title
                setOnClickListener(mOnClickListener)
            }
        }

   inner class ViewHolder(val mView: View) :RecyclerView.ViewHolder(mView{})

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

fun checkHashMapExists(hashMap: HashMap<Long, ABC>?, newValues: ArrayList<OT>){
      for(i in newValues){
         if (hashMap?.keys.toString().contains(i.id)){
             txvTitle.setTextColor(Color.parseColor("#000000")) // txvTitle cannot resolved
         }
      }   
    }

ФрагментА

 override fun onResume() {
        super.onResume()
        mAdapter.checkHashMapExists(hashMap,otList)
    }
1
0
2 019
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Ответ принят как подходящий

Обычно вы не должны использовать ViewHolder вне onBindViewHolder. Весь код, связанный с пользовательским интерфейсом, должен вызываться внутри onBindViewHolder. Лучше вызвать notifyDataSetChanged или другой notifyXXX метод, чтобы перерисовать ваш RecyclerView контент.

Я хочу изменить цвет txvTitle, когда функция вызывается из фрагмента. Как я могу использовать notifyDataSetChanged в этом случае?

John Joe 10.04.2019 20:17

@JohnJoe Добавьте someField к своему адаптеру. Когда функция вызывается из фрагмента, обновите значение someField и вызовите notifyDataSetChanged. Внутри onBindViewHolder вы должны уважать someField. Нравится: if (someField) { use color1} else {use color2}

Andrew Churilo 10.04.2019 20:22

Несмотря на то, что не рекомендую его использовать, вы можете вызвать следующий метод, чтобы получить ViewHolder для элемента данных в позиции i:

MyViewHolder holder = (MyViewHolder) mRecyclerView.findViewHolderForAdapterPosition(i);
if (holder != null) {
    // Do whatever you want
}

Имейте в виду, что документация говорит об этом методе:

Return the ViewHolder for the item in the given position of the data set. Unlike findViewHolderForLayoutPosition(int) this method takes into account any pending adapter changes that may not be reflected to the layout yet. On the other hand, if notifyDataSetChanged() has been called but the new layout has not been calculated yet, this method will return null since the new positions of views are unknown until the layout is calculated.

Вместо этого что бы я сделал, если бы я был тобой должен иметь атрибут в классе вашей модели, который указывает, какой цвет его ViewHolder должен использовать для отображения текста txtView.title.

Затем, когда вы хотите обновить цвет элемента (или элементов) в вашем RecyclerView, вы можете изменить этот атрибут своего класса модели, а затем вызвать notifyDataSetChanged();

Адаптер не может узнать, что означает txvTitle, поскольку он относится к одному элементу в RecyclerView. Однако внутри ViewHolder это свойство (если оно существует) связано с представлением, которое «подготавливается».

Таким образом, обновления представления должны выполняться только в классе ViewHolder.

Взгляните на пример это. В этом примере создается отдельный класс, который расширяет RecyclerView.Viewholder(view). В этом классе определен метод с именем bind, которому передается объект (или модель), который используется для заполнения представления. Метод create увеличивает макет представления, которое будет отображаться в RecyclerView

Я использую notifyDataSetChanged(). Спасибо !

John Joe 11.04.2019 07:47

Вы можете создать функцию в своем классе адаптера, которая принимает Функция высшего порядка в качестве параметра, а затем выставить свой объект ViewHolder в этой функции для использования вне Класс адаптера.

Посмотрите, как это можно сделать:

Допустим, у вас есть Класс адаптера, как показано ниже.

class Adapter {
    ...
    // Here we create object of our Higher order function
    var holderCallback: ((RecyclerView.ViewHolder?) -> Unit)? = null

    //Then We provide callback like below in onBindViewHolder method
    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        ... Some binding stuff
        holderCallback?.let {
           it(holder)
        }
        ... even some more stuff
    }
}

И теперь мы можем получить доступ извне (В вашем случае из класса Fragment)

class Fragment {
    // Here we have adapter object
    ...
    //So, we get our callback like below from any method in here
    ...Inside some method where we receive callback
    adapter.holderCallback { viewHolder: RecyclerView.ViewHolder? -> //Here you've got ViewHolder object
        // Now do some amazing stuff here !!
    }
}

Вы хотите изменить цвет текста элемента держателя на основе этого метода адаптера, верно?

Jeel Vankhede 11.04.2019 04:44

Я. Как я могу передать два параметра из фрагмента в класс адаптера?

John Joe 11.04.2019 04:45

Где эти оба параметра? Являются ли они классом адаптера или классом фрагмента?

Jeel Vankhede 11.04.2019 04:48

Эта строка в FragmentA mAdapter.checkHashMapExists(hashMap,otList)

John Joe 11.04.2019 04:49

Кажется, я не могу ясно понять вашу дилемму.

Jeel Vankhede 11.04.2019 06:50

Другие вопросы по теме