Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Alexander Vasin (prieran) vs CallbackHell #6

Open
wants to merge 6 commits into
base: master
Choose a base branch
from

Conversation

AudasViator
Copy link

@AudasViator AudasViator commented Aug 9, 2016

Теперь здесь есть топорный, но рабочий ContentProvider. Без интернета.
Json лежит в ресурсах и парсится через ArtistProviderImpl.

Итак, как всё работает:

  • Есть MainActivity, оно надувает R.layout.activity_master_detail
  • R.layout.activity_master_detail - ссылка в refs.xml. Для планшетов она ссылается на activity_twopane, для телефона - на activity_onepane. Названия говорят сами за себя.
  • Если надулось activity_twopane, то findViewById(R.id.photo_frame_layout) вернёт нам вьюху (это контейнер справа для фрагмента с фотографий). В телефонной разметки его нет, вернётся null. Так становится ясно, где мы запускаемся
  • Дальше активити создаёт фрагменты. Всё очевидно, кроме того что у ArtistViewPagerFragment две разметки: одна с PagerTabStrip для телефона, другая без него для планшета.
  • У фрагментов есть callback'и, имена методов говорят сами за себя. Активити всё разрулит.

Особенности:

  • Общение с данными идёт через интерфейс ArtistProvider. Синглтон делать не хотелось, Dagger мне пока не подвластен, поэтому вышел стильный, модный, молодёжный dependency injection на колбеках. Как я понимаю, Dagger в идеале должен (если не делать один компонент для всех) передавать компонент через эти же колбеки, но всё нужное инжектить самостоятельно. Поправьте, если не так.
  • ArtistDetailDialogFragment может запускаться как в полноэкранном режиме, так и как типичный диалог.
  • Все ссылки на колбеки (=activity) в нужных местах обёрнуты в WeakReference. Активити не текут, проверено.
  • ViewPager сам сохраняет своё состояние. Состояние RecyclerView'ера в ArtistListFragment сохраняется через IcePick. Причём RecyclerView движется за движением ViewPager. Наверно это удобно.
  • Про FragmentArgs я узнал слишком поздно, поэтому аргументы написаны руками.
  • Красоты нет, лишь бы ничего не падало и было по заданию.

mName.setText(artist.getName());
mGenre.setText(artist.getGenresAsString());
// TODO: Сделать строки нормально
mCount.setText(artist.getCountOfAlbums() + " альбомов, " + artist.getCountOfTracks() + " треков");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Возьми за правило сразу делать строки нормально. Я не ожидал такое увидеть.

Copy link
Author

@AudasViator AudasViator Aug 9, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Хорошо, сейчас поправлю
Спасибо за быструю проверку, даже unbind не успел отправить =)

@zagayevskiy
Copy link
Contributor

Падает на планшете, если повернуть экран и потом нажать на элемент списка.

java.lang.NullPointerException
at ru.yandex.yamblz.ui.fragments.ArtistViewPagerFragment.setCurrentItem(ArtistViewPagerFragment.java:60)
at ru.yandex.yamblz.ui.activities.MainActivity.onArtistInListSelected(MainActivity.java:81)
at ru.yandex.yamblz.ui.adapters.ArtistListRecyclerAdapter$ArtistHolder.onClick(ArtistListRecyclerAdapter.java:79)
at android.view.View.performClick(View.java:4444)
at android.view.View$PerformClick.run(View.java:18440)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5028)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:788)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:604)
at dalvik.system.NativeStart.main(Native Method)

public class ArtistListRecyclerAdapter extends RecyclerView.Adapter<ArtistListRecyclerAdapter.ArtistHolder> {
private ArtistProvider mArtistProvider;
private Picasso mPicasso;
private WeakReference<ArtistListFragment.Callbacks> mCallbacks;
Copy link
Contributor

@zagayevskiy zagayevskiy Aug 9, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Тут пара вещей, которые мне не нравятся. Можно не исправлять, это просто в качестве совета.

  1. ArtistListFragment.Callbacks в адаптере. Ты этим привязал адаптер к фрагменту, и адаптер теперь не переиспользовать без изменения.
  2. WeakReference здесь. Как по мне, это не лучшая практика. Ничему не доверяешь, программа скатывается в пучину проверок, null это или не null. Обнулять вьюхи (а за ними - адаптеры, а потом потеряются ссылки на эти листенеры и всё станет хорошо), по-моему, лучше. Плюс, когда ты делаешь вот так, ответственность за утечки расползается по коду.

P.S. пока писал, придумал ещё минус - если я вдруг захочу адаптеру передать объект, на который нет больше ссылок (анонимный класс, например), всё станет совсем плохо.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants