Комментарии 23
…
Если кто-то в таких ситуациях использует RelativeLayout или nested LinearLayouts, то он тот еще индус.
When onPageFinished() is called, the rendering picture may not be updated yet.
Сам долго воевал с этими нерабочими и deprecated методами. В итоге таки вступил в «клуб элитных мазохистов».
Благодаря тому, что RecyclerView понимает какие айтемы добавились, какие удалились или переместились, оно может красиво эти изменения анимировать после notifyDataSetChanged.
Вот тут есть пара гифок, где видно разницу при смене модели со стабильными ID и без.
Не могли бы вы поподробнее пояснить по поводу isFinishing()
?
Кстати с Acitivity.isFinishing() тоже не всё так гладко: сверните приложение с >1 активити в стэке, дождитесь ситуации нехватки памяти, вернитесь обратно и воспользуйтесь Up Navigation и вуаля!.. Это был простой рецепт того, как поиметь Activity.isFinishing() == false для активити, которые вы больше никогда не увидите.
Предположим следующую ситуацию:
Back Stack: Activity1 -> Activity2 -> [Activity3]
Свернули приложение, дождались нехватки памяти, вернулись обратно, нажали кнопку назад, получили
BackStack: Activity1 -> [Activity2]
Для какой именно Activity я получу isFinishing() == false
? Для Activity3?
По поводу вашего примера. Я упомянул не кнопку 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 убивает целиком процесс.
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. Возникает оно, к сожалению из-за неточной информации в официальной документации, однако даже ведущие инженеры платформы утверждают обратное.
Пожалуй, вставлю в статью ветку с этим рассуждением в таком случае, ибо просто с наскоку сказать нечто вроде «а вы знаете, документация врёт» — не выйдет.
Хочу лишь уточнить, что всё вышесказанное актуально для ситуации нехватки памяти! Система всё ещё может уничтожать отдельные 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 этот механизм больше не работает.
Кюветы Android, Часть 2: SDK и Libraries