Suspend android что это
Энергопотребление (автономность) Xiaomi Redmi Note 10 Pro
M2101K6G
Описание | Обсуждение » | Покупка » | Аксессуары » | Брак и ремонт » | Прошивки » | Энергопотребление »
- Wakelock Detector — Поиск причины незасыпания устройства.
- BetterBatteryStats — Утилита для мониторинга разряда аккумулятора при бездействии телефона.
В теме нет куратора. По вопросам наполнения шапки обращайтесь к модераторам раздела через кнопку под сообщениями, на которые необходимо добавить ссылки.
Сообщение отредактировал sad1968 — 12.07.21, 09:12
Ну чтож, открою ветку своим нытьем.
Обновился тремя точками на 12.0.13
Перезагрузился. Толку ноль.
Сейчас решил посмотреть стандартный список doze.
Подкладываю список приложений, которые не экономят заряд.
Поудалял все ,что только возможно из этого списка. Буду наблюдать.
Сообщение отредактировал imbleble — 13.04.21, 13:01
extr1m, Скан вафли 165 пробуждений, вот и жор батареи. Одним словом прошивка ужасная, оптимизация тоже.
Нужно ждать офф кастомов.
П.с Пробовал отключать вафлю и мобильный иннет, за ночь уходило 0-1%. Думаю, если включить режим полёта, будет ещё лучше.
Сообщение отредактировал fyter — 13.04.21, 22:30
Тоже сегодня за ночь (6 часов) 10% улетело.
Сообщение отредактировал markshejder153 — 14.04.21, 05:37
Здравствуйте ,что за смарт нафиг,продал ми макс 3 2х годовалый ,держал как новый ,за ночь в режиме полета 1% ,тут 11%,это чего за дерьмо от сяоми?такого еще не видел,у всей семьи сяоми разные ,но этот пипец какой то ,отлючено все ,что можно .
Добавлено 14.04.2021, 10:10:
Обнова вчера тоже прилетела ,но был на работе ,там вайфай слабый,хотел скачать но не пошло долго,отключил,удалил ,что успело качнуть,но сегодня дома ее уже нет ,пишет нет обновы .Почему так ,кто подскажет?
Кривая обнова, мерцания, баги все жалуются и обнову отозвали.
Сообщение отредактировал fyter — 14.04.21, 10:55
Добавлено 14.04.2021, 12:54:
Главное как то до этого не замечал ,что ночью сильно разряжается,3% не более.Но эту ночь и в режиме полета . ужас
На прошивке 12.0.10 Global. Пару дней до этого перезагружал смартфон после зарядки, за ночь он тратил 6-7%. Вчера не перезагрузил, но включил режим экономии энергии (bluetooth, wifi и моб.интернет включены, gps нет). За ночь ушло 2% заряда, две третьих которых потратила мобильная связь.
Сообщение отредактировал Kold — 14.05.21, 19:48
Среднестатистическое потребление за день активного просмотра ютуба вансед, где 120 герц даже на видео. Знаю, толку мало, но зато без рекламы. Кроме этого ещё телеграм, инста и ещё по мелочи, 8 часов экрана и 19% остаточного заряда в полночь
Всем привет.
Стояла 12.0.10 2 дня назад. Выходило под 89 часов работы от аккума без зарядки, но 4 часа экрана. Или 10 часов экрана, если ютуб, фото, видео, и не играть. За ночь уходило 1-2 %. Был счастлив, но затем обновился до 12.0.13.
За ночь сегодня с 22 до 6 несколько минут экрана, включен вайфай, зуб, gps отрублен. И что самое интересное — ВЫТЯНУЛ СИМКУ.
Я считаю, ЭТО РЕКОРД.
БЕЗ СИМКИ ЗА 8 ЧАСОВ 0 МИНУТ ЭКРАНА ЗА НОЧЬ МИНУС 25 % батареи ИЛИ 1850 mAh. Как тебе такое, ИЛОН МАСК?)
И разрядился мобильной сетью без симки, как?
Смотрю в сторону 8+, может дам шанс и сброшусь до заводских с обновой до 12.0.10, еще не определился, но это уже на голову не налазит.
Источник
Под капотом модификатора suspend
Корутины Kotlin предоставили Android разработчикам модификатор suspend. Изучив его, вы поймете, почему функция suspend не возвращает ничего до тех пор, пока не будет завершена вся начатая работа, и как код может приостановить работу без блокировки потоков.
TL; DR; компилятор Kotlin создаст конечный автомат для каждой функции suspend, которая управляет выполнением корутины за нас!
Корутины 101
Корутины упрощают асинхронные операции на Android. Как поясняется в документации, мы можем использовать их для управления асинхронными задачами, которые в противном случае могут заблокировать основной поток и привести к зависанию приложения.
Корутины также полезны для замены API, основанных на обратном вызове, на императивно выглядящий код. Например, взгляните на этот асинхронный код, который использует обратные вызовы:
Эти обратные вызовы могут быть преобразованы в последовательные вызовы функций с помощью корутин:
В коде корутин мы добавили модификатор функции suspend. Он говорит компилятору, что эта функция должна выполняться внутри корутины. Как разработчик, вы можете рассматривать suspend как обычную функцию, выполнение которой может быть приостановлено и возобновлено в какой-то момент.
В отличие от обратных вызовов, корутины обеспечивают простой способ переключения между потоками и обработкой исключений.
Но что же на самом деле делает компилятор под капотом, когда мы помечаем функцию как suspend?
Под капотом suspend
Возвращаясь к функции suspend loginUser , обратите внимание, что другие функции, которые она вызывает, также являются функциями suspend:
Если кратко, то компилятор Kotlin берет функции suspend и преобразует их в оптимизированную версию обратных вызовов с использованием конечного автомата, о котором мы поговорим позже.
Вы правильно поняли, компилятор напишет эти обратные вызовы за вас!
Интерфейс Continuation
Таким образом, функции suspend взаимодействуют друг с другом с помощью объектов Continuation . Continuation — это просто общий интерфейс обратного вызова с некоторой дополнительной информацией. Как мы увидим позже, он будет представлять собой сгенерированный конечный автомат функции suspend.
Давайте взглянем на его определение:
- context будет являться CoroutineContext , который будет использоваться в этом продолжении (continuation).
- resumeWith возобновляет выполнение корутины с Result , который может содержать либо значение, являющееся результатом вычисления, вызвавшего приостановку, либо исключение.
Примечание: начиная с Kotlin 1.3 и далее, вы также можете использовать функции расширения resume(value: T) и resumeWithException(exception: Throwable) , которые являются специализированными версиями вызова resumeWith .
Компилятор заменит модификатор suspend дополнительным параметром completion (типа Continuation ) в сигнатуре функции, которая будет использоваться для передачи результата функции suspend вызвавшей ее корутине:
Наш пример вернет Unit вместо User . Объект User будет “возвращен” в добавленном параметре Continuation .
Байт-код функции suspend фактически возвращает Any? , потому что это тип объединения T | COROUTINE_SUSPENDED . Это позволяет функции по возможности возвращаться синхронно.
Примечание: если вы пометите функцию, которая не вызывает другие функции suspend с этим модификатором, компилятор добавит дополнительный параметр Continuation, но ничего с ним не сделает, байт-код тела функции будет выглядеть как обычная функция.
Вы также можете увидеть интерфейс Continuation в других местах:
• При преобразовании API-интерфейсов на основе обратного вызова в корутины с использованием suspendCoroutine или suspendCancellableCoroutine (предпочтительнее) вы непосредственно взаимодействуете с объектом Continuation , чтобы возобновить корутину, которая была приостановлена после выполнения блока кода, переданного в качестве параметра.
• Вы можете запустить корутину с помощью функции расширения startCoroutine для функции suspend. Он принимает объект Continuation в качестве параметра, который будет вызван, когда новая корутина завершится либо результатом, либо исключением.
Применение диспетчеров
Вы можете переключаться между различными диспетчерами для выполнения вычислений в разных потоках. Откуда Kotlin знает, где возобновить приостановленные вычисления?
Существует подтип Continuation , называемый DispatchedContinuation , функция resume которого делает вызов Dispatcher доступным в CoroutineContext . Все диспетчеры будут вызывать отправку, кроме Dispatchers.Unconfined , чье переопределение функции isDispatchNeeded (которая вызывается перед dispatch ) всегда возвращает false .
Сгенерированный конечный автомат
Внимание: код, который будет показан в остальной части статьи, не будет полностью соответствовать байт-коду, сгенерированному компилятором. Это будет код Kotlin, достаточно точный, чтобы позволить вам понять, что на самом деле происходит внутри. Это представление генерируется корутинами версии 1.3.3 и может измениться в будущих версиях библиотеки.
Компилятор Kotlin определит, когда функция может приостановить работу внутри системы. Каждая точка приостановки будет представлена как состояние в конечном автомате. Они представляются компилятором с помощью меток:
Для лучшего представления конечного автомата компилятор будет использовать оператор when для реализации различных состояний:
Этот код является неполным, поскольку различные состояния не имеют возможности обмениваться информацией. Для этого компилятор будет использовать тот же объект Continuation в функции. Вот почему исходный Continuation является Any? вместо возвращаемого типа исходной функции (т. е. User ).
Кроме того, компилятор создаст закрытый класс, который 1) содержит необходимые данные и 2) рекурсивно вызывает функцию loginUser для возобновления выполнения. Вы можете проверить приблизительную реализацию сгенерированного класса ниже.
Внимание: комментарии не генерируются компилятором. Я добавил их, чтобы объяснить, что выполняется в коде.
Поскольку invokeSuspend снова вызовет loginUser только с информацией объекта Continuation , остальные параметры в сигнатуре функции loginUser становятся недействительными. На этом этапе компилятору просто нужно добавить информацию о том, как перемещаться между состояниями.
Первое, что ему нужно сделать, это знать, если 1) это первый раз, когда функция вызывается или 2) функция возобновилась из предыдущего состояния. Так он проверяет, имеет ли переданное continuation тип LoginUserStateMachine или нет:
Если это происходит в первый раз, он создаст новый экземпляр LoginUserStateMachine и сохранит полученный экземпляр completion в качестве параметра, чтобы он помнил, как возобновить функцию, вызвавшую его. Если это не так, то он просто продолжит выполнение конечного автомата (функция suspend).
Теперь давайте рассмотрим код, который компилятор генерирует для перемещения между состояниями и обмена информацией между ними:
Сравните код выше с предыдущими фрагментами. Давайте посмотрим, что генерирует компилятор:
- Аргументом оператора when является label из экземпляра LoginUserStateMachine .
- Каждый раз, когда обрабатывается новое состояние, происходит проверка на случай сбоя, когда эта функция была приостановлена.
- Перед вызовом следующей функции suspend (т. е. logUserIn ) label экземпляра LoginUserStateMachine обновляется до следующего состояния.
- Когда внутри этого конечного автомата происходит вызов другой функции suspend, экземпляр continuation (типа LoginUserStateMachine ) передается в качестве параметра. Вызываемая функция suspend также была преобразована компилятором, и это еще один конечный автомат, подобный тому, который принимает объект continuation в качестве параметра! Когда конечный автомат этой функции suspend завершится, она возобновит его выполнение.
Последнее состояние отличается тем, что оно должно возобновить выполнение функции, которая вызвала эту функцию. Как видно из кода, она вызывает resume для переменной cont , хранящейся (во время построения) в LoginUserStateMachine :
Компилятор Kotlin делает для нас очень много. Из этой функции suspend:
Зная, что делает компилятор под капотом, вы можете лучше понять, почему функция suspend ничего не вернет, пока не будет завершена вся начатая работа. Кроме того, как код может приостановить работу без блокировки потоков: информация о том, что должно быть выполнено при возобновлении функции, хранится в объекте Continuation !
Источник
Урок 1. Корутины. Введение.
В этом уроке начнем разбираться, что такое корутина и suspend функция.
Сложная тема
Не раз я слышал мнение, что официальная документация по корутинам сложна и представляет собой примерно такое:
Я, пожалуй, соглашусь с этим мнением. Нас сразу грузят билдерами, скоупами и suspend функциями. Говорят, что их надо использовать так-то и так-то и будет нам счастье. И вроде даже объясняют, что это такое, но особо понятнее не становится. Но даже несмотря на это я рекомендую вам посмотреть эту документацию, чтобы получить хотя бы примерное представление, что такое корутины и зачем они нужны.
В защиту авторов документации я должен сказать, что тема действительно очень сложна для объяснения. Для меня корутины по сложности легко обошли такие непростые темы, как Dagger или Backpressure в RxJava. Я потратил кучу времени, чтобы разобраться, что же такое корутины и как они работают. Читал официальные доки, делал примеры, читал статьи, смотрел видео. И все равно у меня оставалось ощущение, что я не понимаю их до конца сам, а значит не могу объяснить другим. Пришлось прибегнуть к последнему, самому надежному и самому сложному средству — лезть в исходники. Врагу не пожелаю туда соваться, но в итоге я таки пробился через эти дебри и постепенно пазл собрался.
В этом курсе я собираюсь достаточно подробно осветить тему корутин, используя для этого все то, что мне удалось раскопать. Я буду шаг за шагом расписывать отдельные кусочки пазла и периодически собирать эти кусочки в большие куски, объясняя очередную тему. В итоге у вас должна сложиться общая картина. Иногда может показаться, что я слишком ухожу в дебри объяснений, и эта информация не нужна вовсе, и давайте лучше сразу с боевых примеров начнем! Но тут я исхожу из своего опыта. Мне удалось полностью понять примеры только после того, как я раскопал внутренности. И сейчас моя цель — сделать так, чтобы вы, посмотрев на код с корутинами, могли точно сказать, как он себя поведет. А для этого нужно понять корутины изнутри.
Поэтому первые несколько уроков будут состоять только из объяснений. Я подробно расскажу о том, во что превращается корутина при преобразовании Kotlin кода в Java. А также о том, почему suspend функция не блокирует поток. Об этом будут первые 5 уроков. А уже после этого пойдут более интересные и приближенные к практике темы: Scope, Context, Job и т.п.
Рекомендую не пропускать уроки и идти по ним последовательно, чтобы в последующих уроках все было понятно. А если какой-то урок или раздел можно будет пропустить, я явно напишу об этом.
Краткий вариант уроков
В этом курсе я буду использовать новую технику подачи материала. Если урок содержит много теории и объяснений, то вы сможете прочитать его в одном из двух вариантов: подробном или кратком.
Подробный вариант подходит для тех, кто в теме новичок. В этом случае требуется максимально подробное объяснение темы. Одна и та же мысль может быть рассмотрена несколько раз с разных сторон для лучшего понимания. Читать надо долго и вдумчиво. В этом стиле написано большинство моих уроков на сложные темы.
Краткий вариант подходит для тех, кто уже хоть немного, но знаком с темой. А также тех, кто ранее уже прочел подробный вариант и зашел просто освежить знания или подсмотреть какой-то момент. Тут не будет подробных объяснений и долгого хождения вокруг темы. Все лаконично и тезисно.
Выбирайте вариант, который подходит вам. Можете сразу попробовать краткий вариант для экономии времени. Если видите, что информации недостаточно, и нужно более вдумчивое объяснение, то заваривайте кружку чая, берите плед и открывайте подробный вариант)
Эта опция может некорректно работать на мобильной версии сайта. Я уже написал в техподдержку создателям, жду ответа. В случае возникновения проблем используйте десктопную версию.
Корутина
Непросто подобрать описание, что такое корутина. В самом начале обычно рассматривается такой простой пример:
Этот и последующие несколько примеров выдернуты из контекста и не будут работать без дополнительного кода. Но в целях изучения теории они нам подходят. Практика будет позже.
Здесь launch — это билдер корутины, которому передается небольшой блок кода:
Мы еще рассмотрим очень подробно и по шагам, что происходит под капотом билдера. А пока что нам надо знать только то, что билдер упакует переданный ему блок кода в корутину и запустит ее. Если необходимо, то с помощью входных параметров мы можем указать билдеру, в каком потоке необходимо выполнить этот код.
Если очень упрощать, то можно сказать, что билдер — это экзекьютор, который оборачивает блок кода в Runnable и запускает этот Runnable на выполнение. Т.е. корутину можно представить так:
Казалось бы, все, тему можно закрывать. Корутина — это просто очередной механизм для выполнения асинхронных операций. Но не все так просто.
Корутина имеет ряд особенностей. Например — Job. Когда мы запускаем корутину, мы можем получить Job, как результат запуска билдера:
Это дает нам некоторые возможности по управлению корутиной. Мы можем сделать выполнение кода отложенным (LAZY) и стартовать его позже, когда понадобится. Или в любой момент времени можно будет отменить выполнение. Также можно запускать корутину внутри корутины. Их джобы будут связаны между собой отношениями Parent-Child, что является отдельным механизмом, который влияет на обработку ошибок и отмену корутин. Все это мы еще подробно рассмотрим в дальнейших уроках.
А пока что нас интересует одна из самых важных особенностей корутин — suspend функции.
Suspend функция
Чтобы лучше понять, что это такое, поговорим про потоки. Поток выполнения корутины — это вовсе не обязательно фоновый поток. Им вполне может быть и main поток. В Android мы часто будем запускать корутины в main потоке. И, как мы все знаем, этот поток нельзя блокировать.
В примере выше мы в корутине используем suspend функцию delay. Эта функция приостановит выполнение кода на 1000 мсек, затем выполнение кода продолжится и напишет в лог слово World. Вроде ничего не обычного. Но обратите внимание, я написал «приостановит выполнение кода», а не «заблокирует поток».
В этом и есть ключевая особенность suspend функции. Она не блочит поток. А значит мы можем эту корутину запускать в main потоке. Функция delay приостановит выполнение кода на 1 секунду, но не заблокирует main поток.
Давайте рассмотрим пример, более приближенный к реальности. Например, загрузка файла.
Код без всяких корутин и suspend функций будет таким:
Мы генерируем URL файла и передаем его в функцию download, которая выполнит загрузку. После этого мы выводим Toast-сообщение о том, что файл загружен.
Функция download — синхронная, а значит заблокирует поток, в котором будет выполнена. Но нам хотелось бы выполнить этот код в UI потоке, потому что функция toast может быть выполнена только в нем. Чтобы разрешить это противоречие, нам придется сделать функцию download асинхронной и toast поместить в колбэк, который будет выполнен по завершении загрузки.
Т.е. при запуске тяжелого кода в main потоке нам приходится выбирать из двух зол: блокировка потока или колбэк. Если функция download синхронна — то поток будет заблокирован. А если она асинхронна, то нам придется добавлять колбэк, чтобы выполнить последующий код.
А хорошо было бы сделать так, чтобы долго работающая функция не блокировала поток, но при этом код, который находится после функции, был выполнен по завершении загрузки без всяких колбэков. Использование suspend функций в корутинах позволяют нам сделать это.
Перепишем код с использованием корутины и suspend функции:
Эта корутина не заблокирует поток, в котором будет запущен ее код. Т.е. его можно запустить даже в main потоке. Функция download загрузит файл в отдельном потоке, а toast будет выполнен только после того, как download отработает.
Это кажется магией, но не забывайте, что Kotlin код будет преобразован в Java классы. И во время этих преобразований будет использован механизм Continuation. Он в сочетании с suspend функциями реализует колбэк, который обеспечит выполнение toast только после того, как загрузка файла будет завершена.
О том, как именно это происходит, подробно поговорим в следующем уроке.
Корутина
В самом начале документации и статей обычно рассматривается такой простой пример:
Здесь launch — это билдер корутины, которому передается блок кода. Билдер упакует переданный ему блок кода в корутину и запустит ее.
Когда мы запускаем корутину, мы можем получить Job, как результат запуска билдера:
Это дает нам некоторые возможности по управлению корутиной. Например, мы можем сделать выполнение кода отложенным (lazy) и стартовать его позже, когда понадобится. Или в любой момент времени можно будет отменить выполнение. Также можно запускать корутину внутри корутины. Их джобы будут связаны между собой отношениями Parent-Child, что является отдельным механизмом, который влияет на обработку ошибок и отмену корутин.
Suspend функция
В примере выше мы в корутине используем suspend функцию delay. Эта функция приостановит выполнение кода на 1000 мсек, затем выполнение кода продолжится и напишет в лог слово World. При этом delay не заблокирует поток. В этом и есть ключевая особенность suspend функций. А значит мы можем эту корутину запускать в main потоке.
Давайте рассмотрим пример, более приближенный к реальности. Например, загрузка файла.
Код без всяких корутин и suspend функций будет таким:
Мы генерируем URL файла и передаем его в функцию download, которая выполнит загрузку. После этого мы выводим Toast-сообщение о том, что файл загружен.
Функция download — синхронная, а значит заблокирует поток, в котором будет выполнена. Но нам хотелось бы выполнить этот код в UI потоке, потому что функция toast может быть выполнена только в нем. Чтобы разрешить это противоречие, нам придется сделать функцию download асинхронной и toast поместить в колбэк, который будет выполнен по завершении загрузки.
Использование suspend функций в корутинах позволяют нам выполнять долгие асинхронные функции без колбэков:
Эта корутина не заблокирует поток, в котором она будет запущена. А toast будет выполнен только после того, как download отработает. Это достигается с помощью механизма Continuation, который используется при преобразовании Kotlin кода в Java классы.
О том, как именно это происходит, подробно поговорим в следующем уроке.
Присоединяйтесь к нам в Telegram:
— в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.
— в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование
— ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня
— новый чат Performance для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме
Комментарии
Илья, есть еще такая штука, называется «книга». Можно купить ее и даже прочитать, там кроются сакральные истины о всех этих волшебных конструкциях языка Котлин — стрелочках, скобочках, обобщениях и вот это вот все.
Спасибо автору за этот курс. Тема выбрана просто идеально, ибо я считаю корутины самой сложной частью котлина (еще конечно обрезки от дженериков, но то таке) и давно хотел с этим разобраться. Рад что заскочил сюда и увидел что есть такой курс.
ЗЫ Я довольно долго и упорно гуглил чтобы понять как работают потроха корутин, но нигде нет инфы! Курс — вышка, рекомендую. Человек потратил время, разобрался, расшарил — красавчик
Источник