Я создал ListFragment (знаю, что есть RecyclerView, просто книгу читаю). В методе onAttach я пытаюсь получить ссылку на активность, чтобы вызывать ее метод. После первого запуска — мое приложение не работало. После 10ти минут раздумий я нашел ошибку! onAttach(Context context) не вызывается, а onAttach(Activity activity) (deprecated) — вызывается! Вот методы:
@Override //РАБОТАЕТ
public void onAttach(Activity activity) {
super.onAttach(activity);
listener = (WorkoutListListener) activity;
}
@Override //НЕ РАБОТАЕТ
public void onAttach(Context context) {
super.onAttach(context);
listener = (WorkoutListListener) context;
}
Так в чем же разница этих двух методов? Почему устаревший работает, а обычный нет?
Ответ
Подробно на англо-саксонсом тут
Кратко:
ListFragment есть только в пакете android.app и добавляется в активити через FragmentManager вместо SupportFragmentManager. Из-за этого не используется метод onAttach(Context context) на устройствах с API<23, а используется onAttach(Activity activity)
Решением может быть помечание обоих методов соответствующими аннотациями для вызова нужной версии на определённых уровнях API и делегирование продолжения логики в общий для всех API собственный метод, в коем вы уже можете кастовать контекст к активити (помня, что класс итоговой активити разнится в зависимости от уровня API (решение - кастовать к интерфейсу, реализуемому активити):
/*
* onAttach(Context) не вызовется до API 23 версии вместо этого будет вызван onAttach(Activity), коий устарел с 23 API
* Так что вызовем onAttachToContext
*/
@TargetApi(23)
@Override
public void onAttach(Context context) {
super.onAttach(context);
onAttachToContext(context);
}
/*
* устарел с 23 API
* Так что вызовем onAttachToContext
*/
@SuppressWarnings("deprecation")
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
onAttachToContext(activity);
}
}
/*
* Вызовется в момент присоединения фрагмента к активити
*/
protected void onAttachToContext(Context context) {
//здесь всегда есть контекст и метод всегда вызовется.
//тут можно кастовать контест к активити.
//но лучше к реализуемому ею интерфейсу
//чтоб не проверять из какого пакета активити в каждом из случаев
}
Комментариев нет:
Отправить комментарий