Мне кажется, я придумал очень простой вопрос, который можно задать любому андроид-разработчику, при этом ответ будет либо совсем неправильным, либо неточным (а это по сути неправильный)

Признаюсь, когда я придумал его, мое лицо стало прямо как на картинке ниже:

Лицо человека, знающего правильный ответ
Лицо человека, знающего правильный ответ

Ладно, не буду томить и сразу перейдем к сути. Только давайте договоримся, что не будем гуглить, а сначала подумаем.

Итак, я понимаю, ты ожидаешь какой-то хитрый вопрос, где есть какой-то подвох.
Спойлер -- подвоха НЕТ.

Просто отвечай так, как тебе подсказывает твоя голова.

У нас есть вот такой код:

В onCreate мы просто блокируем главный поток на довольно большое время.
Вопрос: что произойдет с программой? Ответ объясни.

Вот прямой сейчас остановись и дальше не читай. Напиши свой ответ в комментарии, а потом можешь прочитать все, что находится ниже.

Не открывай спойлер раньше времени, не совершай ошибку :-)

Итак, если ты ответил, что будет ANR, то поздравляю - ты абсолютно нормальный человек, у тебя скорее всего много друзей, есть девушка и в целом в жизни все прекрасно. Но ответ неправильный..

Давай разбираться, в чем дело.

1) Дело в runBlocking? Может там диспатчер какой-то необычный?

Ну, это было бы подло назвать вопрос по Android Core, а сам вопрос лежал бы в корутинах. То есть дело не в runBlocking. Он работает так, как ожидается. Просто блокирует текущий поток.

2) Получается дело в самом ANR?

Да, уже очень тепло, осталось вспомнить один момент.

Слово ANR и блокировка потока всегда звучат рядом, когда заходит об этом речь. Мы обычно думаем, что раз поток заблокирован, то через 5 секунд появится окошко: "Приложение не отвечает"

А теперь кульминация: условие для возникновения ANR - это когда входные события (кнопки и сенсорные события) не обрабатываются в течение 5 секунд.

Я думаю, уже стало все понятно, но лучше проговорим.

У нас запускается приложение, в onCreate мы блокируем поток, поэтому другие методы ЖЦ не вызываются. onResume не вызвался, поэтому взаимодействовать с UI мы не можем.
Если взаимодействовать с UI мы не можем, то и условие для ANR мы не выполним. Поэтому приложение будет благополучно ждать, пока мы разблокируем поток, и запустится как обычно.

Интересно, что необязательно нажать на кнопки или другие элементы UI. Можно нажать просто в любую точку экрана и ANR появится.

Возможно, эта инфа не особо важная, без нее жить можно. В реальной разработке ты словишь ANR в любом случае, так как будет тыкать на экран. Но по-моему забавно, так как мы все понимаем, что человек умирает не от сигарет, а от рака, который был спровоцирован сигаретами.

PS
Кто ответил правильно сразу - респект, но, пожалуйста, не забывайте выходить на улицу (без негатива).

Комментарии (28)


  1. Revertis
    28.12.2023 12:11
    +4

    По-моему, должен стрельнуть ANR.

    Edit: юзер всё равно будет тыкать в экран, значит ANR :)


    1. dankeshon_1 Автор
      28.12.2023 12:11
      +1

      Если интересно, можешь лично проверить, но ANR не будет, так как мы просто блокируем main поток

      Главный поинт, который хотел передать - блокировка не вызывает ANR. А вот необработанные входные события (клики) - вызывают

      Вроде мелочь, но, как мне кажется, забавная)


      1. grishkaa
        28.12.2023 12:11
        +1

        Так работает любой GUI-фреймворк, сделанный за последние 30 лет. Если в очереди событий ничего нет, то и то, что её разгребание подвисло, никто не обнаружит. Другое дело, что на десктопах просто в силу их природы событий больше — например, есть события перемещения мыши. Поводил курсором над зависшим окном — уже забил ему очередь.


  1. trump-card
    28.12.2023 12:11
    +4

    Палку кинули в колесо. Что произойдёт с телегой? Должен знать!


    1. dankeshon_1 Автор
      28.12.2023 12:11

      Ну да) Хотя тут вопрос скорее такой - от чего погибает человек: от пистолета или от пули?


      1. IvanPetrof
        28.12.2023 12:11
        +1

        От повреждения органов и кровопотери?


      1. DmitryOlkhovoi
        28.12.2023 12:11

        от пороха и физики


        1. freeExec
          28.12.2023 12:11

          Капаем глубже - от угля


          1. Snakecatcher
            28.12.2023 12:11
            +1

            От отравления свинцом.


  1. amateur80lvl
    28.12.2023 12:11

    Ну, раз сначала комент, то понеслась:

    • Напутано с отступами. Любители фигурных скобок - они такие. На питон вас надо.

    • Несоответствие комментария и функции. "Пошоркать часики", так что-ли?

    • Ну если это всё-таки runBlocking, тогда это немного разрыв шаблона. Надо определиться, чего мы хотим - run или blocking? Но если и то и другое - наверняка run бесконечно вызывает вот эту хрень, что блокирует выполнение потока, а потом переключает асинхронный контекст и так до бесконечности. Только вот вопрос: зачем это делать в OnCreate?

    Вот такие мысли об офигительном дизайне приходят на ум дилетанту, который яву брал в руки 12 лет назад, а писать для мобилок до сих пор желания нет.


    1. dankeshon_1 Автор
      28.12.2023 12:11

      хахах, да, за наблюдательность с комментарием лайк)

      Понятно, что это вымышленный пример. Никто так делать не будет.
      Просто все разработчики знают, что такое ANR, но даже тут можно ошибиться)

      а runBlocking это из корутин штука, блокирует поток (если кратко)


  1. Neikist
    28.12.2023 12:11
    +1

    Почему то подумал что вопрос в том отрисуется или нет вью. И по идее не отрисуется, ибо хоть вью заинфлейтится и добавится, но насколько помню после этого только выставляются requestLayout и invalidate, а измерение, размещение и отрисовка уже на следующем шаге лупера выполнится.

    З.Ы. А зачем runBlocking если Thread.sleep уже достаточно? А если уж runBlocking, тогда задачка была бы веселей если внутри delay вызвать вместо Thread.sleep, чтобы дополнительно запутать.


    1. dankeshon_1 Автор
      28.12.2023 12:11

      Кстати, да, хорошее замечание. Я просто изначально с delay тестил, но решил на обычный Thread.sleep чтобы не путать людей с корутинами

      c delay интереснее, согласен)


  1. Plesser
    28.12.2023 12:11

    Я тут недавно с другой задачкой столкнулся,

    Создаем функцию function без параметров, затем перегружаем ее но уже с параметром который имеет значение по умолчанию. Теперь вызываем функцию не передавая в нее параметры. Какая функция вызовется и почему.

    ps

    С наступающим кстати!


    1. Neikist
      28.12.2023 12:11

      Для override же сигнатура совпадать должна. На уровне байткода если дефолтные параметры есть - несколько методов генерируется, мне кажется компилятор ошибку должен кидать.

      А если речь просто про создание функций с одинаковым именем но разной сигнатурой (где в одном случае все параметры значение по умолчанию имеют, а в другом параметров нет) - то по идее на уровне байткода та что с дефолтными параметрами - эти самые параметры иметь все равно будет. В таком случае, кмк, либо компилятор ругнется, либо вызовет ту что на уровне байткода без параметров (ибо совместимость с java, все дела).


      1. Plesser
        28.12.2023 12:11

        не ругнется, но кстати мне что то в голову не пришло декомпилировать в java код

        ps

        кстати в чистом котлине действительно будет вызываться всегда функция которая без параметров.а вот в Android Emulator, у меня изредка почему то вызывалась функция с параметрами. Но возможно это глюки именно эмулятора...


        1. Neikist
          28.12.2023 12:11

          Странно конечно. На уровне байткода сигнатуры прям разные должны быть что в jvm обычных, что в dex. Так что поведение должно быть одинаковое при каждом запуске, смотря какую сигнатуру компилятор в месте вызова прописал. И прописывать он по идее должен сигнатуру без параметров.

          Разве что jit странно отрабатывает... Но по идее опять же, в байткоде четко должен быть вызов без параметров. jit ничего сломать не должен.


  1. Pan_brigadir
    28.12.2023 12:11

    Просто покажется белый экран. Layout активити отрисуется на следующем кадре после того, как таймаут закончится.


    1. Neikist
      28.12.2023 12:11

      Ну не обязательно белый, на последних адроидах же сплеш скрин можно задавать который перед стартом рисуется.


  1. TranE91
    28.12.2023 12:11
    +1

    Задавая такой вопрос на собеседовании, что Вы хотите проверить у кандидата?


    1. dmt_ovs
      28.12.2023 12:11

      Видимо проверить факт "ты абсолютно нормальный человек, у тебя скорее всего много друзей, есть девушка и в целом в жизни все прекрасно" (с)


    1. dankeshon_1 Автор
      28.12.2023 12:11

      Например, чтобы не спрашивать "Что такое ANR?" можно привести этот пример с блокировкой

      Даже если человек скажет, что ANR не будет, можно спросить - почему?
      И если называет условие возникновения ANR, то он молодец. Это показывает, что человек умеет работать с деталями

      Но я бы не судил уровень кандидата по такому вопросу) Это просто рубрика "Эксперименты"


  1. okmyan
    28.12.2023 12:11

    Мне кажется, что будет справедливо добавить, что вот такой код вызовет ANR. И стоило бы побольше расписать момент, что в изначальном примере ANR не будет, потому что юай в целом не отобразится и юая не будет как такового, поэтому не будет возможности блокировать юай и соответственно вызвать ANR. Не сразу понял, в чем загвоздка. Неподготовленного разработчика это может ввести в заблуждение


    1. dankeshon_1 Автор
      28.12.2023 12:11

      Уточню - ты нажал на кнопку и больше никуда не нажимал на экране?

      Просто я сделал такой же код, но у меня не появляется ANR (если после нажатия на кнопку никуда не кликать)

      Насчет пояснения - согласен!




      1. okmyan
        28.12.2023 12:11

        Да, да, конечно, надо кликнуть куда-нибудь на экране после нажатия на кнопку


  1. Alexeg86
    28.12.2023 12:11

    Первое, что пришло в голову - ОС сочтёт, что приложение повисло и предложит его закрыть...


  1. yeswolf
    28.12.2023 12:11

    Вопрос из разряда "мне кажется, что я тут познал ньюансы, пострадаю-ка я хернёй на собеседовании за счёт конторы". Не познал, даже близко.

    "Задержка на UI thread = падение приложения" это, для начала, альфа и омега любой мобильной оси по состоянию "десять лет назад". Никаких там пяти секунд, не надо терзаться. Сразу, иногда и без показа UI. То, что на какой-то оси теперь это по другому, никак не меняет простой основы: так делать нельзя. И это единственный правильный ответ.

    Не надо филигранно направлять незаряженный 9мм на человека - потому что не заряжен он сегодня, а завтра очередной копатель в ньюансах решит, что нашел идеальный угол снятого предохранителя, при котором на него можно дунуть и он снимется, а так не, стрелять не будет. Ну, пока оппонент не чихнет.

    Копания в нюансах подобного типа с начинающими приведет к тому, что они где-то решат "так не рухнет же сразу, использую". И потом ровно этот же собеседующий будет разгребать последствия в виде лапши, от которой падает очередной билд.

    Умельцы работать с деталями, господь жги. А потом после таких умельцев двадцатилетний код, который надо вывести в асинхрон, бо он из-за "знания ньюансов" втыкает на каждом шагу, а умельцы сидят и рассказывают тебе, как же это теперь невыразимо сложно.


  1. MaximPestryakov
    28.12.2023 12:11

    Где можно получить оффер, если я ответил правильно?