Мне кажется, я придумал очень простой вопрос, который можно задать любому андроид-разработчику, при этом ответ будет либо совсем неправильным, либо неточным (а это по сути неправильный)
Признаюсь, когда я придумал его, мое лицо стало прямо как на картинке ниже:
Ладно, не буду томить и сразу перейдем к сути. Только давайте договоримся, что не будем гуглить, а сначала подумаем.
Итак, я понимаю, ты ожидаешь какой-то хитрый вопрос, где есть какой-то подвох.
Спойлер -- подвоха НЕТ.
Просто отвечай так, как тебе подсказывает твоя голова.
У нас есть вот такой код:
В onCreate мы просто блокируем главный поток на довольно большое время.
Вопрос: что произойдет с программой? Ответ объясни.
Вот прямой сейчас остановись и дальше не читай. Напиши свой ответ в комментарии, а потом можешь прочитать все, что находится ниже.
Не открывай спойлер раньше времени, не совершай ошибку :-)
Итак, если ты ответил, что будет ANR, то поздравляю - ты абсолютно нормальный человек, у тебя скорее всего много друзей, есть девушка и в целом в жизни все прекрасно. Но ответ неправильный..
Давай разбираться, в чем дело.
1) Дело в runBlocking? Может там диспатчер какой-то необычный?
Ну, это было бы подло назвать вопрос по Android Core, а сам вопрос лежал бы в корутинах. То есть дело не в runBlocking. Он работает так, как ожидается. Просто блокирует текущий поток.
2) Получается дело в самом ANR?
Да, уже очень тепло, осталось вспомнить один момент.
Слово ANR и блокировка потока всегда звучат рядом, когда заходит об этом речь. Мы обычно думаем, что раз поток заблокирован, то через 5 секунд появится окошко: "Приложение не отвечает"
А теперь кульминация: условие для возникновения ANR - это когда входные события (кнопки и сенсорные события) не обрабатываются в течение 5 секунд.
Я думаю, уже стало все понятно, но лучше проговорим.
У нас запускается приложение, в onCreate мы блокируем поток, поэтому другие методы ЖЦ не вызываются. onResume не вызвался, поэтому взаимодействовать с UI мы не можем.
Если взаимодействовать с UI мы не можем, то и условие для ANR мы не выполним. Поэтому приложение будет благополучно ждать, пока мы разблокируем поток, и запустится как обычно.
Интересно, что необязательно нажать на кнопки или другие элементы UI. Можно нажать просто в любую точку экрана и ANR появится.
Возможно, эта инфа не особо важная, без нее жить можно. В реальной разработке ты словишь ANR в любом случае, так как будет тыкать на экран. Но по-моему забавно, так как мы все понимаем, что человек умирает не от сигарет, а от рака, который был спровоцирован сигаретами.
PS
Кто ответил правильно сразу - респект, но, пожалуйста, не забывайте выходить на улицу (без негатива).
Комментарии (28)
trump-card
28.12.2023 12:11+4Палку кинули в колесо. Что произойдёт с телегой? Должен знать!
dankeshon_1 Автор
28.12.2023 12:11Ну да) Хотя тут вопрос скорее такой - от чего погибает человек: от пистолета или от пули?
amateur80lvl
28.12.2023 12:11Ну, раз сначала комент, то понеслась:
Напутано с отступами. Любители фигурных скобок - они такие. На питон вас надо.
Несоответствие комментария и функции. "Пошоркать часики", так что-ли?
Ну если это всё-таки runBlocking, тогда это немного разрыв шаблона. Надо определиться, чего мы хотим - run или blocking? Но если и то и другое - наверняка run бесконечно вызывает вот эту хрень, что блокирует выполнение потока, а потом переключает асинхронный контекст и так до бесконечности. Только вот вопрос: зачем это делать в OnCreate?
Вот такие мысли об офигительном дизайне приходят на ум дилетанту, который яву брал в руки 12 лет назад, а писать для мобилок до сих пор желания нет.
dankeshon_1 Автор
28.12.2023 12:11хахах, да, за наблюдательность с комментарием лайк)
Понятно, что это вымышленный пример. Никто так делать не будет.
Просто все разработчики знают, что такое ANR, но даже тут можно ошибиться)
а runBlocking это из корутин штука, блокирует поток (если кратко)
Neikist
28.12.2023 12:11+1Почему то подумал что вопрос в том отрисуется или нет вью. И по идее не отрисуется, ибо хоть вью заинфлейтится и добавится, но насколько помню после этого только выставляются requestLayout и invalidate, а измерение, размещение и отрисовка уже на следующем шаге лупера выполнится.
З.Ы. А зачем runBlocking если Thread.sleep уже достаточно? А если уж runBlocking, тогда задачка была бы веселей если внутри delay вызвать вместо Thread.sleep, чтобы дополнительно запутать.
dankeshon_1 Автор
28.12.2023 12:11Кстати, да, хорошее замечание. Я просто изначально с delay тестил, но решил на обычный Thread.sleep чтобы не путать людей с корутинами
c delay интереснее, согласен)
Plesser
28.12.2023 12:11Я тут недавно с другой задачкой столкнулся,
Создаем функцию function без параметров, затем перегружаем ее но уже с параметром который имеет значение по умолчанию. Теперь вызываем функцию не передавая в нее параметры. Какая функция вызовется и почему.
ps
С наступающим кстати!
Neikist
28.12.2023 12:11Для override же сигнатура совпадать должна. На уровне байткода если дефолтные параметры есть - несколько методов генерируется, мне кажется компилятор ошибку должен кидать.
А если речь просто про создание функций с одинаковым именем но разной сигнатурой (где в одном случае все параметры значение по умолчанию имеют, а в другом параметров нет) - то по идее на уровне байткода та что с дефолтными параметрами - эти самые параметры иметь все равно будет. В таком случае, кмк, либо компилятор ругнется, либо вызовет ту что на уровне байткода без параметров (ибо совместимость с java, все дела).
Plesser
28.12.2023 12:11не ругнется, но кстати мне что то в голову не пришло декомпилировать в java код
ps
кстати в чистом котлине действительно будет вызываться всегда функция которая без параметров.а вот в Android Emulator, у меня изредка почему то вызывалась функция с параметрами. Но возможно это глюки именно эмулятора...
Neikist
28.12.2023 12:11Странно конечно. На уровне байткода сигнатуры прям разные должны быть что в jvm обычных, что в dex. Так что поведение должно быть одинаковое при каждом запуске, смотря какую сигнатуру компилятор в месте вызова прописал. И прописывать он по идее должен сигнатуру без параметров.
Разве что jit странно отрабатывает... Но по идее опять же, в байткоде четко должен быть вызов без параметров. jit ничего сломать не должен.
Pan_brigadir
28.12.2023 12:11Просто покажется белый экран. Layout активити отрисуется на следующем кадре после того, как таймаут закончится.
Neikist
28.12.2023 12:11Ну не обязательно белый, на последних адроидах же сплеш скрин можно задавать который перед стартом рисуется.
TranE91
28.12.2023 12:11+1Задавая такой вопрос на собеседовании, что Вы хотите проверить у кандидата?
dmt_ovs
28.12.2023 12:11Видимо проверить факт "ты абсолютно нормальный человек, у тебя скорее всего много друзей, есть девушка и в целом в жизни все прекрасно" (с)
dankeshon_1 Автор
28.12.2023 12:11Например, чтобы не спрашивать "Что такое ANR?" можно привести этот пример с блокировкой
Даже если человек скажет, что ANR не будет, можно спросить - почему?
И если называет условие возникновения ANR, то он молодец. Это показывает, что человек умеет работать с деталями
Но я бы не судил уровень кандидата по такому вопросу) Это просто рубрика "Эксперименты"
okmyan
28.12.2023 12:11Мне кажется, что будет справедливо добавить, что вот такой код вызовет ANR. И стоило бы побольше расписать момент, что в изначальном примере ANR не будет, потому что юай в целом не отобразится и юая не будет как такового, поэтому не будет возможности блокировать юай и соответственно вызвать ANR. Не сразу понял, в чем загвоздка. Неподготовленного разработчика это может ввести в заблуждение
dankeshon_1 Автор
28.12.2023 12:11Уточню - ты нажал на кнопку и больше никуда не нажимал на экране?
Просто я сделал такой же код, но у меня не появляется ANR (если после нажатия на кнопку никуда не кликать)
Насчет пояснения - согласен!
Alexeg86
28.12.2023 12:11Первое, что пришло в голову - ОС сочтёт, что приложение повисло и предложит его закрыть...
yeswolf
28.12.2023 12:11Вопрос из разряда "мне кажется, что я тут познал ньюансы, пострадаю-ка я хернёй на собеседовании за счёт конторы". Не познал, даже близко.
"Задержка на UI thread = падение приложения" это, для начала, альфа и омега любой мобильной оси по состоянию "десять лет назад". Никаких там пяти секунд, не надо терзаться. Сразу, иногда и без показа UI. То, что на какой-то оси теперь это по другому, никак не меняет простой основы: так делать нельзя. И это единственный правильный ответ.
Не надо филигранно направлять незаряженный 9мм на человека - потому что не заряжен он сегодня, а завтра очередной копатель в ньюансах решит, что нашел идеальный угол снятого предохранителя, при котором на него можно дунуть и он снимется, а так не, стрелять не будет. Ну, пока оппонент не чихнет.
Копания в нюансах подобного типа с начинающими приведет к тому, что они где-то решат "так не рухнет же сразу, использую". И потом ровно этот же собеседующий будет разгребать последствия в виде лапши, от которой падает очередной билд.
Умельцы работать с деталями, господь жги. А потом после таких умельцев двадцатилетний код, который надо вывести в асинхрон, бо он из-за "знания ньюансов" втыкает на каждом шагу, а умельцы сидят и рассказывают тебе, как же это теперь невыразимо сложно.
Revertis
По-моему, должен стрельнуть ANR.
Edit: юзер всё равно будет тыкать в экран, значит ANR :)
dankeshon_1 Автор
Если интересно, можешь лично проверить, но ANR не будет, так как мы просто блокируем main поток
Главный поинт, который хотел передать - блокировка не вызывает ANR. А вот необработанные входные события (клики) - вызывают
Вроде мелочь, но, как мне кажется, забавная)
grishkaa
Так работает любой GUI-фреймворк, сделанный за последние 30 лет. Если в очереди событий ничего нет, то и то, что её разгребание подвисло, никто не обнаружит. Другое дело, что на десктопах просто в силу их природы событий больше — например, есть события перемещения мыши. Поводил курсором над зависшим окном — уже забил ему очередь.