Вызов метода из RecyclerView, полученного с помощью отражения

Мне нужно получить доступ к методам RecyclerView, созданного с использованием сторонней библиотеки. Что я делаю, так это получаю представление RecyclerView с помощью findViewById:

ViewGroup mainView = mainActivity.getWindow().getDecorView().findViewById(android.R.id.content);
    if (feedView == null){
        Object okStreamRecyclerView =  mainView.findViewById(NEWSFEED_RECYCLER_ID);
        feedView = (okStreamRecyclerView.getClass().getSuperclass()).getSuperclass();
        scrollToTop(feedView);
    }

На данный момент feedView.getSimpleName приводит к RecyclerView. Затем я пытаюсь прокрутить это RecyclerView вверх, используя:

private void scrollToTop(Class feedView) {
        log("THE VIEW IS OF TYPE: "+feedView.getName()); // androidx.recyclerview.widget.RecyclerView
        try {
            Method method = feedView.getMethod("getLayoutManager");
            method.setAccessible(true);
            LinearLayoutManager layoutManager = (LinearLayoutManager) method.invoke(feedView);
            layoutManager.scrollToPositionWithOffset(0, 0);
        } catch (NoSuchMethodException e) {
           log("NO SUCH METHOD EXCEPTION",e);
        } catch (IllegalAccessException e) {
            log("ILLEGAL ACCESS EXCEPTION",e);
        } catch (InvocationTargetException e) {
            log("INVOCATION TARGET EXCEPTION",e);
        }
    }

но по какой-то причине я получаю сообщение об ошибке ниже:

IllegalArgumentException: Expected receiver of type androidx.recyclerview.widget.RecyclerView, but got java.lang.Class<androidx.recyclerview.widget.RecyclerView>

Как я могу преобразовать класс в ожидаемый RecyclerView? Есть ли другой способ получить это представление?

Превратите okStreamRecyclerView в RecyclerView и вызовите getLayoutManager(), и избавьтесь от всех отражений.

CommonsWare 17.06.2019 17:05

@CommonsWare это первое, что я попробовал. Но по какой-то причине я получил исключение, которое не может привести к RecyclerView. Даже когда okStream расширяет класс, расширяющий RecyclerView. Может быть, это не удается, потому что проект, генерирующий okstream, использует андроидx, а я нет?

113408 17.06.2019 17:17

«Может ли это произойти из-за того, что проект, генерирующий okstream, использует androidx, а я нет?» -- да, поскольку есть отдельные RecyclerView классы. Сочетание классов библиотеки поддержки и AndroidX — это в первую очередь рискованное предложение, поэтому я бы порекомендовал вам перенести свой собственный код на AndroidX, если вы собираетесь использовать эту библиотеку. В качестве альтернативы, если вы хотите попробовать использовать его как есть, убедитесь, что RecyclerView, к которому вы приводите, — это androidx.recyclerview.widget.RecyclerView.

CommonsWare 17.06.2019 17:20

@CommonsWare Я использовал версию Androidx, но все равно получаю java.lang.ClassCastException: StreamRecyclerView cannot be cast to androidx.recyclerview.widget.g (я не понимаю конец имени класса). Именно по этой причине я обратился к размышлению. Любая идея, как обойти это?

113408 17.06.2019 17:31

Является ли библиотека, которую вы используете, открытым исходным кодом?

CommonsWare 17.06.2019 17:45

@CommonsWare К сожалению, нет, поэтому я обратился к размышлению, поскольку это казалось последним вариантом. Я как бы близок к тому, чтобы вытащить это, но это исключение приведения находится в пути, и я не уверен, почему. Также я не могу объяснить, почему я не могу привести к родительскому классу. Бессмыслица для меня.

113408 17.06.2019 18:01

@CommonsWare Если у ВАС нет решения этой проблемы, я могу просто сдаться...

113408 19.06.2019 11:10

Ваша ошибка связана с передачей feedView в invoke() - вы должны передавать okStreamRecyclerView (объект, для которого вы пытаетесь вызвать getLayoutManager()). Я подозреваю, что вы столкнетесь с каким-то другим сбоем, как будто приведение не работает, потому что okStreamRecyclerView не является RecyclerView, тогда отражение также должно завершиться ошибкой, если только StreamRecyclerView не имеет своего собственного метода getLayoutManager().

CommonsWare 19.06.2019 13:06
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
8
72
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Благодаря подсказке @CommonsWare мне удалось вызвать метод ScrollToPosition с помощью отражения. Вот рабочий код в моем конкретном случае, может быть проще в каком-то другом сценарии:

View okStreamRecyclerView = null;
            try {
                okStreamRecyclerView = mainView.findViewById(NEWSFEED_RECYCLER_ID);
                feedView = (okStreamRecyclerView.getClass().getSuperclass()).getSuperclass();
                Method method = feedView.getMethod("getLayoutManager");
                method.setAccessible(true);
                LinearLayoutManager layoutManager = (LinearLayoutManager) method.invoke(okStreamRecyclerView);
                Class llm = layoutManager.getClass().getSuperclass();
                Method m2 = llm.getMethod("scrollToPositionWithOffset",int.class, int.class);
                m2.setAccessible(true);
                m2.invoke(layoutManager,0,0);
            } catch (ClassCastException e){
                log("AN EXECPTON OCCURED WHILE FETCHING VIEW",e);
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }

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