Как использовать функцию, которая привязана к фрагменту, внутри адаптера RecyclerView
Есть функция, которая вызывает определенный эффект вибрации:
public fun Fragment.vibratePhoneClick(){
val vibrator = context?.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
if (Build.VERSION.SDK_INT >= 29) {
vibrator.vibrate(VibrationEffect.createPredefined(VibrationEffect.EFFECT_TICK))
} else {
vibrator.vibrate(20)
}
}
Я хочу использовать ее внутри обработчика нажатия, который находится в recyclerview (вынести обработчик в onViewCreated невозможно):
class RecyclerViewAdapter(...) : ... {
...
override fun onBindViewHolder(...){
holder.itemView.setOnClickListener {
vibratePhoneClick()
}
...
}
Но студия выдает:
Unresolved reference.
None of the following candidates is applicable because of receiver type mismatch:
public fun Fragment.vibratePhoneClick(): Unit defined in com.example.kotlindiary in file MainFragment.kt
При этом, внутри метода onViewCreated эта функция срабатывает идеально
Я полагаю, вся соль как раз в том, что я объявляю функцию как Fragment.vibratePhoneClick(), а не vibratePhoneClick(), но тогда теряется контекст. Я сам не очень разбираюсь в том, как правильно применять контекст, но, вдруг, если кто-то знает толковую статью, был бы благодарен ссылке
Ответы (2 шт):
Раз для вибро требуется Context, то лучше сделать основное расширение на Context
public fun Context.vibratePhoneClick() {
val vibrator = getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
if (Build.VERSION.SDK_INT >= 29) {
vibrator.vibrate(VibrationEffect.createPredefined(VibrationEffect.EFFECT_TICK))
} else {
vibrator.vibrate(20)
}
}
// расширение для фрагмента
public fun Fragment.vibratePhoneClick() = requireContext().vibratePhoneClick()
А Context можно получить из View
override fun onBindViewHolder(...) {
holder.itemView.setOnClickListener {
it.context.vibratePhoneClick()
}
}
Не обрабатывайте клик внутри адаптера. Это не его ответственность. Создайте интерфейс вроде такого:
interface Listener {
fun onClick(data: YourData) // если вам не нужны никакие аргументы - можете ничего не передавать
}
Реализуйте его внутри вашей Activity/Fragment. Передайте в ваш адаптер ссылку на него к примеру через конструктор (или метод сеттер):
class RecyclerViewAdapter(private val listener: Listener) {
...
override fun onBindViewHolder(...) {
holder.itemView.setOnClickListener {listener.onClick(data[position])}
}
}
И вызывайте спокойно в вашем фрагменте вашу функцию vibrator.vibrate(20)