Мне нужно получить доступ к методам 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? Есть ли другой способ получить это представление?
@CommonsWare это первое, что я попробовал. Но по какой-то причине я получил исключение, которое не может привести к RecyclerView. Даже когда okStream расширяет класс, расширяющий RecyclerView. Может быть, это не удается, потому что проект, генерирующий okstream, использует андроидx, а я нет?
«Может ли это произойти из-за того, что проект, генерирующий okstream, использует androidx, а я нет?» -- да, поскольку есть отдельные RecyclerView классы. Сочетание классов библиотеки поддержки и AndroidX — это в первую очередь рискованное предложение, поэтому я бы порекомендовал вам перенести свой собственный код на AndroidX, если вы собираетесь использовать эту библиотеку. В качестве альтернативы, если вы хотите попробовать использовать его как есть, убедитесь, что RecyclerView, к которому вы приводите, — это androidx.recyclerview.widget.RecyclerView.
@CommonsWare Я использовал версию Androidx, но все равно получаю java.lang.ClassCastException: StreamRecyclerView cannot be cast to androidx.recyclerview.widget.g (я не понимаю конец имени класса). Именно по этой причине я обратился к размышлению. Любая идея, как обойти это?
Является ли библиотека, которую вы используете, открытым исходным кодом?
@CommonsWare К сожалению, нет, поэтому я обратился к размышлению, поскольку это казалось последним вариантом. Я как бы близок к тому, чтобы вытащить это, но это исключение приведения находится в пути, и я не уверен, почему. Также я не могу объяснить, почему я не могу привести к родительскому классу. Бессмыслица для меня.
@CommonsWare Если у ВАС нет решения этой проблемы, я могу просто сдаться...
Ваша ошибка связана с передачей feedView в invoke() - вы должны передавать okStreamRecyclerView (объект, для которого вы пытаетесь вызвать getLayoutManager()). Я подозреваю, что вы столкнетесь с каким-то другим сбоем, как будто приведение не работает, потому что okStreamRecyclerView не является RecyclerView, тогда отражение также должно завершиться ошибкой, если только StreamRecyclerView не имеет своего собственного метода getLayoutManager().




Благодаря подсказке @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();
}
Превратите
okStreamRecyclerViewвRecyclerViewи вызовитеgetLayoutManager(), и избавьтесь от всех отражений.