Как стать автором
Обновить

Комментарии 23

По воле случая на первую работу попал на андроид вместо энтерпрайза. Ох… Теперь иначе отношусь к стереотипу о кривых приложениях на андроиде.
Очень полезно. Спасибо.
Спасибо. Interceptor — некая прослойка которая может вставлять стандартные хедеры (и не только) во все запросы в Retrofit/okHTTP я правильно понял?
Первый пункт не понял вообще, довольно часто пользуюсь TableLayout и в приведенном примере он подходит идеально. Будет у нас что-то вроде этого



Если кто-то в таких ситуациях использует RelativeLayout или nested LinearLayouts, то он тот еще индус.
Да, вы правы. Не совсем удачно подобрал картинку. На деле бывает нужно уместить сразу 2-3 поля в одну строку (типа такого или такого). Насколько мне известно, в TableLayout этого сделать нельзя (кстати, тут же и советуют RelativeLayout и LinearLayout от которых вы отреклись. Подобные советы вижу довольно часто и сам когда начинал использовал именно LinearLayout'ы)
В чем проблема в макет с webView добавить еще прогрессбар? Переопределяю вызовы `onPageStarted()` и `onPageFinished` у WebViewClient и соответственно показываю/скрываю прогресс
Да хотя бы в том, что:
When onPageFinished() is called, the rendering picture may not be updated yet.

Сам долго воевал с этими нерабочими и deprecated методами. В итоге таки вступил в «клуб элитных мазохистов».
onPageFinished() может сработать раньше, чем контент действительно доступен. В соответствующем пункте я оставил ссылки на stackoverflow с обсуждением этого вопроса. Вот один из тамошних комментариев.
Хочется добавить, что основной бонус от RecyclerView.Adapter.setHasStableIds(true) — это анимации изменений модели.
Благодаря тому, что RecyclerView понимает какие айтемы добавились, какие удалились или переместились, оно может красиво эти изменения анимировать после notifyDataSetChanged.
Вот тут есть пара гифок, где видно разницу при смене модели со стабильными ID и без.
Ссылка не вставилась, вот линк на гифки https://github.com/ArkadyGamza/MasteringRecyclerView_StableIDs/issues/1
RecyclerView и без этого флага может красиво анимироваться, если правильно ему об этом сообщать.
Да, можно использовать notifyItemInserted/Moved/и т.д. Но это не всегда удобно. Например, если модель приходит с сервера.
Не удобно, да. А как влияет то, что модель приходит с сервера? Позиция элемента же никак на это не завязана.
Это просто как пример той ситуации, когда неудобно (мы не знаем что изменилось в модели). Да, конечно, мы можем сами посчитать разницу и сообщить RecyclerView через notifyItemSmth, но гораздо удобнее передать модель целиком и сказать notifyDataSetChanged. RecyclerView сделает всю работу по вычислению изменений (если есть stable IDs) и покажет эти изменения визуально.

Не могли бы вы поподробнее пояснить по поводу isFinishing()?


Кстати с Acitivity.isFinishing() тоже не всё так гладко: сверните приложение с >1 активити в стэке, дождитесь ситуации нехватки памяти, вернитесь обратно и воспользуйтесь Up Navigation и вуаля!.. Это был простой рецепт того, как поиметь Activity.isFinishing() == false для активити, которые вы больше никогда не увидите.

Предположим следующую ситуацию:
Back Stack: Activity1 -> Activity2 -> [Activity3]
Свернули приложение, дождались нехватки памяти, вернулись обратно, нажали кнопку назад, получили
BackStack: Activity1 -> [Activity2]
Для какой именно Activity я получу isFinishing() == false? Для Activity3?

Изначально я собирался описать это отдельным кюветом, но потом решил оставить только Fragment.isRemoving(), а об этом упомянуть вскользь… зря видимо :)
По поводу вашего примера. Я упомянул не кнопку back, а Up Navigation. Это иное. Оно работает по принципу Intent.FLAG_ACTIVITY_CLEAR_TOP. То есть, будет следующее:
Юзер свернул приложение и сейчас для него верно: Back Stack: Activity1 -> Activity2 -> Activity3.
Произошла нехватка памяти и Activity1, Activity2 и Activity3 получили Activity.onDestroy() с Activity.isFinishing() равное false.
В обычной ситуации юзер просто возвращается в приложение, где воссоздается Activity3, затем нажимает кнопку back, из-за которой воссоздается Activity2 и уничтожается Activity3 с Activity.isFinishing() равное true. Однако это не наш случай.
Activity3 имеет возможность при помощи Up Navigation вернуться к Activity1. В итоге, когда юзер вернется в приложение и нажмет на Up Navigation, будет:
1. Воссоздано Activity3
2. Уничтожено Activity3
3. Воссоздано Activity1
4. Вычищен stack
Думаю, тут вы уже и сами догадались. Activity2 было утеряно, а последний его вызов Activity.onDestroy() был с Activity.isFinishing() равное false. Это и есть неприятная ситуация о которой я упомянул.

Всё было бы так если бы Android при недостатке памяти уничтожал только Activity, однако при нехватке памяти Android убивает целиком процесс.

Хм, возможно действительно это называется не так. Я столкнулся с этим конечно же не благодаря тому, что дожидался момента нехватки памяти. Я использовал опцию Don't Keep Activities в dev-настройках. Гугл говорит, что:
Tells the system to destroy an activity as soon as it is stopped (as if Android had to reclaim memory). This is very useful for testing the onSaveInstanceState(Bundle) / onCreate(android.os.Bundle) code path, which would otherwise be difficult to force. Choosing this option will probably reveal a number of problems in your application due to not saving state. For more information about saving an activity's state, see the Activities document.

«if Android had to reclaim memory» — возможно тут я недопонял, в каких именно случаях андроид хочет выгрузить лишь Activity, а не цельный App.
«if Android had to reclaim memory» — возможно тут я недопонял, в каких именно случаях андроид хочет выгрузить лишь Activity, а не цельный App.

Это одно из самых больших заблуждений среди разработчиков Android — что система может удалять из памяти отдельные Activity. Возникает оно, к сожалению из-за неточной информации в официальной документации, однако даже ведущие инженеры платформы утверждают обратное.

Да это же заслуживает masterprice из всех кюветов андроида! Просто невероятно!
Пожалуй, вставлю в статью ветку с этим рассуждением в таком случае, ибо просто с наскоку сказать нечто вроде «а вы знаете, документация врёт» — не выйдет.

Хочу лишь уточнить, что всё вышесказанное актуально для ситуации нехватки памяти! Система всё ещё может уничтожать отдельные Activity, например если таск висит в фоне долгое время. Цитата из документации:


If the user leaves a task for a long time, the system clears the task of all activities except the root activity. When the user returns to the task again, only the root activity is restored. The system behaves this way, because, after an extended amount of time, users likely have abandoned what they were doing before and are returning to the task to begin something new.

Однако для уничтоженных таким образом Activity isFinishing() будет корректно возвращать true. Но даже здесь похоже документация привирает! Есть небезосновательные подозрения, что начиная с определённой версии Android этот механизм больше не работает.

Спасибо за совет с заголовками секций для RecyclerView — это действительно изящно и просто. Но, к сожалению, я не вижу варианта для сетки (к примеру, сетки картинок) — тут всё-таки придётся набрасывать менее изящные схемы.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Изменить настройки темы

Истории