Почему я получаю это исключение из AutoclearedValue?

#android #kotlin

#Android #kotlin

Вопрос:

Я использую AutoclearedValue в Android, и на моем старом планшете, который работает под управлением Android 4.4.4, я всегда получаю исключение, подобное этому: никогда не следует вызывать auto-cleared-value get, если оно может быть недоступно из класса AutoclearedValue

Я не понимаю, почему, потому что на более новых устройствах я не получаю это исключение.

Сценарий следующий: я нажимаю элемент в recyclerview, после чего откроется другой фрагмент. В этом фрагменте я реализовал простой прослушиватель scrollview, он отлично работает. Когда я нажимаю кнопку «Назад», чтобы вернуться к предыдущему фрагменту, я получаю исключение.

Мой класс AutoClearedValue:

 class AutoClearedValue<T : Any>(val fragment: Fragment) : ReadWriteProperty<Fragment, T> {
    private var _value: T? = null

    init {
        fragment.lifecycle.addObserver(object: DefaultLifecycleObserver {
            override fun onCreate(owner: LifecycleOwner) {
                fragment.viewLifecycleOwnerLiveData.observe(fragment) { viewLifecycleOwner ->
                    viewLifecycleOwner?.lifecycle?.addObserver(object: DefaultLifecycleObserver {
                        override fun onDestroy(owner: LifecycleOwner) {
                            _value = null
                        }
                    })
                }
            }
        })
    }

    override fun getValue(thisRef: Fragment, property: KProperty<*>): T {
        return _value ?: throw IllegalStateException(
            "should never call auto-cleared-value get when it might not be available"
        )
    }

    override fun setValue(thisRef: Fragment, property: KProperty<*>, value: T) {
        _value = value
    }
}

/**
 * Creates an [AutoClearedValue] associated with this fragment.
 */
fun <T : Any> Fragment.autoCleared() = AutoClearedValue<T>(this)
 

И мой слушатель, откуда берется исключение:

     private fun initListeners() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            binding.freightTaskRowDetailScrollView.setOnScrollChangeListener { _, _, scrollY, _, oldScrollY ->
                if (binding.showFab == true) {
                    if (scrollY <= oldScrollY) {
                        if (!binding.expandableFab.isShown)
                            binding.expandableFab.showHide()
                    } else {
                        if (binding.expandableFab.isShown)
                            binding.expandableFab.showHide()
                    }
                }
            }
        } else {
            binding.freightTaskRowDetailScrollView.viewTreeObserver
                .addOnScrollChangedListener {
                    if (binding.showFab == true) { [this line]
                        if (!binding.freightTaskRowDetailScrollView.canScrollVertically(1)) {
                            if (binding.expandableFab.isShown)
                                binding.expandableFab.showHide()
                        }
                        if (!binding.freightTaskRowDetailScrollView.canScrollVertically(-1)) {
                            if (!binding.expandableFab.isShown)
                                binding.expandableFab.showHide()
                        }
                    }
                }
        }
    }

 

Ответ №1:

Обновить:

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

https://itnext.io/an-update-to-the-fragmentviewbindingdelegate-the-bug-weve-inherited-from-autoclearedvalue-7fc0a89fcae1

СТАРЫЙ ОТВЕТ

У вас СТАРАЯ версия этого класса.

Проверьте новую реализацию здесь:

https://github.com/android/architecture-components-samples/blob/7be0ea4d9fb07fa51dbd75b0fc656be86de6fc2a/GithubBrowserSample/app/src/main/java/com/android/example/github/util/AutoClearedValue.kt