В этом руководстве представлены лучшие практики и рекомендуемая архитектура для создания надежных и высококачественных приложений.
Пользовательский опыт мобильного приложения
Типичное приложение Android содержит несколько компонентов приложения , включая действия , фрагменты , службы , поставщиков контента и приемники широковещательных сообщений . Большинство этих компонентов приложения вы объявляете в манифесте приложения . Затем ОС Android использует этот файл, чтобы решить, как интегрировать ваше приложение в общий пользовательский интерфейс устройства. Учитывая, что типичное приложение Android может содержать несколько компонентов и что пользователи часто взаимодействуют с несколькими приложениями за короткий период времени, приложениям необходимо адаптироваться к различным видам рабочих процессов и задач, управляемых пользователем.
Имейте в виду, что мобильные устройства также ограничены в ресурсах, поэтому в любой момент операционная система может завершить некоторые процессы приложения, чтобы освободить место для новых.
Учитывая условия этой среды, компоненты вашего приложения могут запускаться индивидуально и не по порядку, и операционная система или пользователь могут уничтожить их в любой момент. Поскольку эти события не находятся под вашим контролем, вам не следует хранить или хранить в памяти какие-либо данные приложения или состояние в компонентах вашего приложения, а компоненты вашего приложения не должны зависеть друг от друга.
Общие архитектурные принципы
Если вам не следует использовать компоненты приложения для хранения данных и состояния приложения, как вместо этого вам следует спроектировать свое приложение?
Поскольку приложения Android растут в размерах, важно определить архитектуру, которая позволит приложению масштабироваться, повысит его надежность и упростит его тестирование.
Архитектура приложения определяет границы между частями приложения и обязанности, которые должна иметь каждая часть. Чтобы удовлетворить упомянутые выше потребности, вам следует спроектировать архитектуру своего приложения так, чтобы она следовала нескольким конкретным принципам.
Разделение интересов
Самый важный принцип, которому следует следовать, – это разделение задач . Распространенной ошибкой является запись всего кода в Activity
или Fragment
. Эти классы на основе пользовательского интерфейса должны содержать только логику, которая обрабатывает взаимодействие пользовательского интерфейса и операционной системы. Сохраняя эти классы как можно более компактными, вы можете избежать многих проблем, связанных с жизненным циклом компонентов, и улучшить тестируемость этих классов.
Имейте в виду, что у вас нет реализаций Activity
и Fragment
; скорее, это просто связующие классы, которые представляют собой контракт между ОС Android и вашим приложением. ОС может уничтожить их в любой момент в зависимости от взаимодействия с пользователем или из-за системных условий, таких как нехватка памяти. Чтобы обеспечить удовлетворительное взаимодействие с пользователем и более управляемое обслуживание приложений, лучше всего свести к минимуму вашу зависимость от них.
Управляйте пользовательским интерфейсом на основе моделей данных
Еще один важный принцип заключается в том, что вы должны создавать свой пользовательский интерфейс на основе моделей данных, предпочтительно постоянных моделей. Модели данных представляют данные приложения. Они независимы от элементов пользовательского интерфейса и других компонентов вашего приложения. Это означает, что они не привязаны к жизненному циклу пользовательского интерфейса и компонентов приложения, но все равно будут уничтожены, когда ОС решит удалить процесс приложения из памяти.
Постоянные модели идеальны по следующим причинам:
Ваши пользователи не потеряют данные, если ОС Android уничтожит ваше приложение, чтобы освободить ресурсы.
Ваше приложение продолжает работать в случаях, когда сетевое соединение нестабильно или недоступно.
Если вы основываете архитектуру своего приложения на классах модели данных, вы делаете свое приложение более тестируемым и надежным.
Единый источник истины
Когда в вашем приложении определен новый тип данных, вам следует назначить ему единый источник истины (SSOT). SSOT является владельцем этих данных, и только SSOT может их изменять или видоизменять. Для этого SSOT предоставляет данные с использованием неизменяемого типа, а для изменения данных SSOT предоставляет функции или получает события, которые могут вызывать другие типы.
Этот шаблон дает несколько преимуществ:
- Он централизует все изменения определенного типа данных в одном месте.
- Он защищает данные, чтобы другие типы не могли их подделать.
- Это делает изменения в данных более отслеживаемыми. Таким образом, ошибки легче обнаружить.
В автономном приложении источником достоверных данных обычно является база данных. В некоторых других случаях источником истины может быть ViewModel или даже пользовательский интерфейс.
Однонаправленный поток данных
Принцип единого источника истины часто используется в наших руководствах с шаблоном однонаправленного потока данных (UDF). В UDF состояние течет только в одном направлении. События , которые изменяют поток данных в противоположном направлении.
В Android состояние или данные обычно передаются из типов иерархии с более высокой областью действия в типы с более низкой областью действия. События обычно запускаются из типов с более низкой областью действия, пока не достигнут SSOT для соответствующего типа данных. Например, данные приложения обычно передаются из источников данных в пользовательский интерфейс. Пользовательские события, такие как нажатия кнопок, передаются из пользовательского интерфейса в SSOT, где данные приложения изменяются и предоставляются в неизменяемом типе.
Этот шаблон лучше гарантирует согласованность данных, менее подвержен ошибкам, его легче отлаживать и он использует все преимущества шаблона SSOT.
Рекомендуемая архитектура приложения
В этом разделе показано, как структурировать ваше приложение в соответствии с рекомендуемыми рекомендациями.
Учитывая общие архитектурные принципы, упомянутые в предыдущем разделе, каждое приложение должно иметь как минимум два уровня:
- Уровень пользовательского интерфейса , отображающий данные приложения на экране.
- Уровень данных , который содержит бизнес-логику вашего приложения и предоставляет данные приложения.
Вы можете добавить дополнительный уровень, называемый уровнем домена , чтобы упростить и повторно использовать взаимодействие между пользовательским интерфейсом и уровнями данных.

Современная архитектура приложений
Эта современная архитектура приложений поощряет использование, среди прочего, следующих методов:
- Реактивная и многоуровневая архитектура.
- Однонаправленный поток данных (UDF) на всех уровнях приложения.
- Уровень пользовательского интерфейса с держателями состояний для управления сложностью пользовательского интерфейса.
- Сопрограммы и потоки.
- Лучшие практики внедрения зависимостей.
Дополнительные сведения см. в следующих разделах, на других страницах «Архитектура» в оглавлении и на странице рекомендаций , содержащей сводку наиболее важных рекомендаций.
Уровень пользовательского интерфейса
Роль уровня пользовательского интерфейса (или уровня представления ) — отображение данных приложения на экране. Всякий раз, когда данные изменяются, либо из-за взаимодействия с пользователем (например, нажатия кнопки), либо из-за внешнего ввода (например, ответа сети), пользовательский интерфейс должен обновляться, чтобы отразить изменения.
Уровень пользовательского интерфейса состоит из двух вещей:
- Элементы пользовательского интерфейса, отображающие данные на экране. Вы создаете эти элементы с помощью функций Views или Jetpack Compose .
- Держатели состояний (например, классы ViewModel ), которые содержат данные, предоставляют их пользовательскому интерфейсу и обрабатывают логику.

Чтобы узнать больше об этом слое, посетите страницу «Слой пользовательского интерфейса» .
Уровень данных
Уровень данных приложения содержит бизнес-логику . Бизнес-логика — это то, что придает ценность вашему приложению: она состоит из правил, которые определяют, как ваше приложение создает, хранит и изменяет данные.
Уровень данных состоит из репозиториев , каждый из которых может содержать от нуля до многих источников данных . Вам следует создать класс репозитория для каждого типа данных, которые вы обрабатываете в своем приложении. Например, вы можете создать класс MoviesRepository
для данных, связанных с фильмами, или класс PaymentsRepository
для данных, связанных с платежами.

Классы репозитория отвечают за следующие задачи:
- Предоставление данных остальной части приложения.
- Централизация изменений в данных.
- Разрешение конфликтов между несколькими источниками данных.
- Абстрагирование источников данных от остальной части приложения.
- Содержит бизнес-логику.
Каждый класс источника данных должен нести ответственность за работу только с одним источником данных, которым может быть файл, сетевой источник или локальная база данных. Классы источников данных являются мостом между приложением и системой для операций с данными.
Дополнительную информацию об этом слое см. на странице уровня данных .
Слой домена
Уровень домена — это дополнительный уровень, который находится между уровнями пользовательского интерфейса и данных.
Уровень предметной области отвечает за инкапсуляцию сложной бизнес-логики или простой бизнес-логики, которая повторно используется несколькими моделями представления. Этот уровень является необязательным, поскольку не все приложения будут соответствовать этим требованиям. Его следует использовать только при необходимости — например, для решения сложных задач или для обеспечения возможности повторного использования.

Классы на этом уровне обычно называются вариантами использования или интеракторами . Каждый вариант использования должен нести ответственность за одну функциональность. Например, ваше приложение может иметь класс GetTimeZoneUseCase
, если несколько моделей ViewModel используют часовые пояса для отображения правильного сообщения на экране.
Чтобы узнать больше об этом слое, посетите страницу слоя домена .
Управление зависимостями между компонентами
Классы в вашем приложении зависят от других классов для правильной работы. Для сбора зависимостей определенного класса можно использовать любой из следующих шаблонов проектирования:
- Внедрение зависимостей (DI) . Внедрение зависимостей позволяет классам определять свои зависимости, не создавая их. Во время выполнения за предоставление этих зависимостей отвечает другой класс.
- Локатор сервисов : шаблон локатора сервисов предоставляет реестр, в котором классы могут получать свои зависимости, а не создавать их.
Эти шаблоны позволяют масштабировать ваш код, поскольку они предоставляют четкие шаблоны для управления зависимостями без дублирования кода и усложнения. Более того, эти шаблоны позволяют быстро переключаться между тестовой и производственной реализациями.
Мы рекомендуем следовать шаблонам внедрения зависимостей и использовать библиотеку Hilt в приложениях Android. Hilt автоматически конструирует объекты, проходя по дереву зависимостей, предоставляет гарантии времени компиляции для зависимостей и создает контейнеры зависимостей для классов платформы Android.
Общие рекомендации
Программирование — творческая область, и создание приложений для Android — не исключение. Есть много способов решить проблему; вы можете передавать данные между несколькими действиями или фрагментами, получать удаленные данные и сохранять их локально для автономного режима или обрабатывать любое количество других распространенных сценариев, с которыми сталкиваются нетривиальные приложения.
Хотя следующие рекомендации не являются обязательными, в большинстве случаев их следование делает вашу кодовую базу более надежной, тестируемой и поддерживаемой в долгосрочной перспективе:
Не храните данные в компонентах приложения.
Не назначайте точки входа вашего приложения, такие как действия, службы и приемники вещания, в качестве источников данных. Вместо этого им следует координировать свои действия только с другими компонентами для получения подмножества данных, имеющих отношение к этой точке входа. Срок службы каждого компонента приложения довольно недолговечен, в зависимости от взаимодействия пользователя со своим устройством и общего текущего состояния системы.
Уменьшите зависимости от классов Android.
Компоненты вашего приложения должны быть единственными классами, которые полагаются на API-интерфейсы SDK платформы Android, такие как Context
или Toast
. Отделение от них других классов в вашем приложении помогает улучшить тестируемость и уменьшает связанность внутри вашего приложения.
Создайте четко определенные границы ответственности между различными модулями вашего приложения.
Например, не распределяйте код, загружающий данные из сети, на несколько классов или пакетов в вашей кодовой базе. Аналогично, не определяйте в одном классе несколько несвязанных обязанностей, таких как кэширование и привязка данных. Следование рекомендуемой архитектуре приложения поможет вам в этом.
Как можно меньше подвергайте воздействию каждого модуля.
Например, не поддавайтесь искушению создать ярлык, раскрывающий детали внутренней реализации модуля. В краткосрочной перспективе вы можете выиграть немного времени, но тогда вы, скорее всего, многократно столкнетесь с техническим долгом по мере развития вашей кодовой базы.
Сосредоточьтесь на уникальности своего приложения, чтобы оно выделялось среди других приложений.
Не изобретайте велосипед, снова и снова написав один и тот же шаблонный код. Вместо этого сосредоточьте свое время и силы на том, что делает ваше приложение уникальным, и позвольте библиотекам Jetpack и другим рекомендуемым библиотекам справиться с повторяющимся шаблоном.
Подумайте, как сделать каждую часть вашего приложения тестируемой по отдельности.
Например, наличие четко определенного API для получения данных из сети упрощает тестирование модуля, который сохраняет эти данные в локальной базе данных. Если вместо этого вы смешаете логику этих двух модулей в одном месте или распределите сетевой код по всей базе кода, эффективное тестирование станет гораздо сложнее, если вообще возможно.
Типы отвечают за свою политику параллелизма.
Если тип выполняет длительную блокирующую работу, он должен нести ответственность за перемещение этих вычислений в правильный поток. Этот конкретный тип знает тип вычислений, которые он выполняет, и в каком потоке они должны выполняться. Типы должны быть безопасными для основного потока, то есть их можно безопасно вызывать из основного потока, не блокируя его.
Сохраняйте как можно больше актуальных и свежих данных.
Таким образом, пользователи смогут пользоваться функциями вашего приложения, даже если их устройство находится в автономном режиме. Помните, что не всем вашим пользователям нравится постоянное высокоскоростное соединение, а даже если и они это делают, они могут получить плохой сигнал в людных местах.
Преимущества архитектуры
Наличие хорошей архитектуры в вашем приложении приносит много преимуществ проектным и инженерным группам:
- Это улучшает удобство обслуживания, качество и надежность всего приложения.
- Это позволяет приложению масштабироваться. Больше людей и больше команд могут вносить свой вклад в одну и ту же базу кода с минимальными конфликтами кода.
- Это помогает при адаптации. Поскольку архитектура обеспечивает согласованность вашего проекта, новые члены команды могут быстро освоиться и работать более эффективно за меньшее время.
- Это легче протестировать. Хорошая архитектура поощряет более простые типы, которые, как правило, легче тестировать.
- Ошибки можно исследовать методично с помощью четко определенных процессов.
Инвестиции в архитектуру также оказывают прямое влияние на ваших пользователей. Они получают выгоду от более стабильного приложения и большего количества функций благодаря более продуктивной команде инженеров. Однако архитектура также требует первоначальных вложений времени. Чтобы помочь вам оправдать это время перед остальными сотрудниками вашей компании, взгляните на эти тематические исследования , в которых другие компании делятся своими историями успеха при наличии хорошей архитектуры в своих приложениях.
Образцы
Следующие примеры Google демонстрируют хорошую архитектуру приложения. Изучите их, чтобы увидеть это руководство на практике:
Mir 2: Return of the King 是 Actoz Soft 授权的优质《传奇》IP 移动游戏,由 HK ZHILI YAOAN LIMITED 使用 Unity 游戏引擎开发。 这款游戏不仅完美再现了韩国奇幻类 MMORPG 的代表作 Mir 2 的游戏氛围,还提供了许多最受欢迎的游戏内容,例如装备收集、大规模沙漠攻击和其他核心玩法。 该游戏使用了 Android Frame Pacing 库 (Swappy) 来提高帧速率的稳定性、实现流畅的渲染,并显著提升了 Android 鸣潮 是一款由 Kuro Games 开发的高保真动作角色扮演游戏。为了持续为长时间的游戏会话提供卓越的用户体验,优化功耗非常重要。 Android Studio 从 Hedgehog (2023.1.1) 开始引入了 功耗性能分析器 ,可帮助开发者根据设备端电源轨监视器 (ODPM) 了解功耗数据。 借助 Android Studio 中的功耗性能分析功能,您还可以 有效地对 Android 应用功能的功耗进行 A/B 测试 (如下所示)。 Kuro Games 首先使用 Android Godot Engine 是一个广受欢迎的多平台开源游戏引擎,对 Android 提供强大的支持。Godot 可用于制作几乎任何类型的游戏,并且支持 2D 和 3D 图形。Godot 4 版引入了新的渲染系统,该系统具有用于高保真图形的高级功能。Godot 4 渲染程序专为 Vulkan 等现代图形 API 而设计。 Godot Foundation 聘请了 The Forge Interactive 的图形优化专家,并与 Google 合作分析和进一步改进了 Godot 4 Vulkan Android 动态性能框架 (ADPF) 是 Google 推出的一款强大工具,适用于希望优化应用性能的开发者。ADPF 通过其热管理 API 提供有关设备热状态的实时信息,这些信息随后用于调整应用中的图形设置。 出于研究目的,Arm 使用 Unreal Engine 和 ADPF 开发了一个演示版,以研究如何使用 ADPF 优化游戏性能。 ADPF 会监控热状态,并相应地在游戏引擎中调整图形质量。 NCSoft《天堂 W》是由 NCSoft 开发的大型多人在线角色扮演游戏 (MMORPG)。这款游戏继承了原始 Lineage W 游戏的传统,为世界各地的玩家提供了一个环境,让他们可以通过全球服务器进行合作和竞争。《Lineage W》以独特的中世纪奇幻世界为背景,通过各种职业、技能和战斗系统为玩家提供深层次的游戏体验。 NCSoft 使用 Android 动态性能框架最大限度地提高了图形质量,同时避免了由温控调频导致的性能问题。 Android 动态性能框架 (ADPF) 改进性能和散热管理对于开发成功的 Android 游戏至关重要。传统上,开发者必须通过降低游戏保真度或进一步优化渲染程序来管理这些问题。这些更改往往针对特定游戏,并且往往不够灵活。 Android 生态系统中的多个参与者为开发者提供了自适应性能 API。为了简化自适应性能功能的集成并减少生态系统中的碎片化,Google 和 MediaTek 携手合作集成了我们的产品:Android 动态性能框架 (ADPF) 和 MediaTek 自适应游戏技术 (MAGT)。 借助 ADPF 使命召唤:战争地带移动版 是广受欢迎的《使命召唤》系列中的第一人称动作游戏。 超受欢迎的主机和 PC 游戏的移动实现利用低层级移动 API 来提供出色的玩家体验。 从技术角度来看,移动实现的目标是支持各种 Android 移动设备,同时尽可能使实现与主机版本保持一致,并确保图形管道和工具链与当前的主机和 PC 游戏及内容保持兼容。 Call of Duty 引擎使用名为 任务图渲染程序 的系统实现渲染提交管理的同步、内存分配和调度,该系统确定在 GPU 《魔灵召唤:克罗尼柯战记》 是韩国游戏开发商 Com2uS 于 2023 年 3 月面向全球发布的一款移动端大型多人在线角色扮演游戏。迄今为止,《魔灵召唤》在全球的下载量超过 1.8 亿,收入超过 27 亿美元。《魔灵召唤》是目前全球最受欢迎的手游之一,这款游戏展现了一个奇幻世界,玩家必须收集并训练各种怪物,才能与其他玩家对战。 近十年过去了,这款游戏庞大的玩家社区依然很是活跃,而且仍在扩展,部分原因在于 Com2uS 不断发布新的内容和更新,使这款游戏历久弥新、十分刺激。Com2uS 《魔灵召唤:克罗尼柯战记》 US(WW) 和 KR by Com2uS 专门利用 Vulkan 在 Android 上进行渲染,可将性能提升高达 30%。 Vulkan 是一种现代化的跨平台 3D 图形 API,旨在最大限度减少设备图形硬件与您的游戏之间的抽象。与 OpenGL ES 相比,Vulkan 的 CPU 开销更低,并且 Vulkan 提供更广泛的功能。 Com2uS 为 《魔灵召唤:克罗尼柯战记》 开发了高级渲染功能,包括: 《魔灵召唤:克罗尼柯战记》 对 Android 《Ares: Rise of Guardians 》是一款移动设备转 PC 的科幻 MMORPG 游戏,由 Second Dive 开发,后者是一家位于韩国的游戏工作室,以其动作角色扮演系列开发方面的专业知识而闻名。该游戏由 Kakao Games 发布。 《阿瑞斯》以广袤的宇宙为背景,采用细节满满的未来主义背景。《阿瑞斯》充满了刺激的玩法和画面精美的角色,涉及身着战斗服的战斗人员。然而,由于这些细节丰富的图形,一些用户的设备在处理游戏内容时有些吃力。 Cat Daddy Games 是一家全资 2K 工作室,位于华盛顿州柯克兰,是 NBA 2K Mobile 的开发者。该团队希望提高游戏的整体质量和稳定性,具体方法是减少“应用无响应”错误 (ANR)。如果 Android 应用的界面线程处于阻塞状态的时间过长,就会发生 ANR。发生这种情况时,负责更新界面的应用主线程将无法绘制或处理用户输入事件,这会引起用户的不满。如果应用在前台运行,系统会显示一个对话框,允许用户强制退出应用。 减少 ANR 一直是 Cat Daddy 的首要任务。QA Devsisters 是一家全球性的移动游戏开发商和发布商,专门制作基于《跑跑姜饼人》IP 的休闲游戏。他们最受欢迎的游戏包括 《跑跑姜饼人:烤箱大逃亡》 (跑步街机)和 《跑跑王国》 (社交 RPG),这两款游戏都深受全球用户的喜爱,尤其是在韩国、台湾和美国。虽然《跑跑姜饼人:烤箱大逃亡》是一款休闲游戏,但五年积累的资源使 CDN 容量提高到了 2.5GB,这使得 CDN 费用的增加。Devsisters 需要找到一种可持续的模式来宣传他们的大文件游戏。 Devsisters 发现,大量的 NEW STATE Mobile 是 Krafton 的一款大逃杀游戏于 2021 年 11 月面向全球发布,在发布后的第一个月便获得了超过 4500 万次下载。KRAFTON, Inc. 是一个由多个独立的游戏开发工作室组成的联合公司,旨在为全球游戏玩家打造富有吸引力的创新娱乐体验。该公司包括 PUBG Studio、Bluehole Studio、Striking Distance Studio、RisingWings、Dreamotion 和 Unknown Spokko 住在波兰,是一群雄心勃勃的创作者,他们致力于打造要求极为严苛的 IP。Spokko 是 CD PROJEKT 家族的成员,但是一家独立公司,已将 《巫师:怪物杀手》 的精彩世界转移到智能手机上。 《巫师:怪物杀手》是一款使用增强现实技术的基于位置的角色扮演游戏。这是一款计算密集型游戏,会给许多设备带来挑战。发布之初,Spokko 希望确保其游戏可以覆盖尽可能多的用户,同时为所有人提供高品质的体验。 Cat Daddy Games 是一家全资 2K 工作室,总部位于华盛顿州柯克兰。NBA 2K Mobile、NBA SuperCard 和 WWE SuperCard 系列背后的团队正在寻找一个解决方案来为用户提高游戏的整体质量,具体方法是在支持这些游戏的设备上提供更优质的素材资源。 他们实现了 Play Asset Delivery,以简单而更灵活的方式针对每位用户的设备配置生成并提供经过优化的 APK,并使用纹理压缩格式定位功能针对特定设备提供更好的美术资源并减少资源下载。 首先,Cat Unreal Engine 是由 Epic Games 开发的游戏引擎,可为各行各业的创作者提供自由和控制权,让他们提供先进的娱乐、富有吸引力的可视化内容和沉浸式虚拟世界。一些主要的 Android 游戏都是使用 Unreal Engine 构建的。 图 1. 在 Pixel 4 上运行的 Unreal Engine Suntemple 示例的屏幕截图 Epic 和其他游戏开发者使用 Android Studio 调试 C++、Kotlin 或 Java 编程语言,但许多游戏开发者都有以 Electronic Arts (EA) 是一家总部位于美国加利福尼亚州的游戏公司。它制作了各种不同类型的游戏,例如体育、动作、赛车和模拟游戏。EA 的开发工作室 Firemonkeys 因开发 真实赛车 3 、 模拟人生自由玩 和 Need For Speed: No Limits 而闻名于世。Firemonkeys 使用自定义游戏引擎来开发游戏,现在他们的所有 Android 游戏都在其开发工作流中使用 Android Game Development Extension (AGDE) 游戏开发商 CD Projekt RED (CDPR) 位于波兰华沙,他们重新构思了自己的迷你游戏《巫师 3》、 《巫师之昆特牌》 ,并于 2020 年 3 月在 Google Play 上以独立的免费畅玩形式发布。由于初始文件较大,且定期更新需要额外的设备存储空间,用户通常必须重新安装完整版游戏,才能获得更新的版本。这是游戏社区中最突出的挫败点。为了帮助进行差分修补,CDPR 通过实现 Play Asset Delivery 取得了巨大的成功。 CDPR 是实现 Play Asset 20 多年来, Gameloft 为数字平台打造了富有创意的游戏体验,从移动游戏到跨平台 PC 和主机游戏,不一而足。除了自有的知名游戏系列外,Gameloft 还为乐高、环球和长宝等热门品牌开发游戏。他们的游戏团队在全球拥有 3,600 名员工,每月可在 100 多个国家/地区覆盖 5500 万唯一身份玩家。 竞速街机游戏 Asphalt 9: Legends 于 2018 年首次发布,他们需要找到一种平衡性能、保真度和电池的方式。为此,Gameloft 怀着对游戏的热情以及将游戏带给世界各地玩家的渴望, Gameloft 于 2000 年成立。他们是开发移动游戏的先驱,现在旗下有超过 190 款游戏。Gameloft 的许多移动游戏是图形密集型游戏,下载大小较大。这使得他们成为 Google Play Asset Delivery (PAD) 早期开发阶段一个极具吸引力的合作伙伴。PAD 是一套基于我们的 app bundle 基础架构构建的游戏服务分发功能。PAD 会在适当的时间免费向适当的设备提供免费、动态的适当游戏素材资源。这引起了 RV AppStudios 是一家总部位于美国的游戏开发商,该公司旗下的休闲游戏、教育儿童应用和实用类应用到目前为止已有超过 2 亿的下载量。该团队在其应用 Puzzle Kids - Animals Shapes and Jigsaw Puzzles 中引入了 Google Play Asset Delivery,属于早期测试用户。他们希望优化应用的大小,节省资金,并在需要下载新的资源包时消除任何干扰,从而提升用户体验。 当用户安装 Puzzle Kids Pixonic 是一个总部位于莫斯科的视频游戏开发团队,其以抓住每一个机会升级自己的移动应用并覆盖更广泛的玩家群体为荣。该公司最著名的游戏之一是 《War Robots》 ,这是一款 12 人的玩家对战 (PVP) 游戏,玩家可以在即时战场上操作定制的机器人进行决斗。 《War Robots》于 2014 年发布,最初是专为 Android 的早期设备设计的,通过触控板操控游戏角色,用不到鼠标。Pixonic Gameloft 一直致力于成为首批在最新便携式硬件上发布游戏的开发商之一,以便随时随地为玩家提供激动人心的体验。因此,Gameloft 知道 ChromeOS 是适合其移动赛车系列最新游戏《狂野飙车 8:极速凌云》的平台。 Gameloft 非常了解如何针对不同的设备开发游戏,但将 Asphalt 体验转换为 Chromebook 特有的触摸屏/键盘混合控制(可随时切换)似乎具有挑战性。然而,结果证明这个过程没有想象的那么困难,值得一试。 利用 ChromebookMir 2 通过使用 Frame Pacing 库来提升渲染性能
Kuro Games 使用 Android Studio 功耗性能分析器和 ODPM 为 Wuthering Waves 降低了 9.68% 的功耗
适用于 Android 的 Godot Engine Vulkan 优化
在 Unreal Engine 中使用 Android 动态性能框架 (ADPF) 入门
NCSoft Lineage W 使用 ADPF 提高了持续性能并防止温控降频
MediaTek 提升了 Android SoC 的动态性能
《使命召唤:战争地带手游》使用 Vulkan 提升图形效果
Com2uS - Google Play 游戏电脑版
Com2uS 使用 Vulkan 提升图形效果
Kakao Games 通过 Android 自适应功能将 FPS 稳定性提升至 96%
2K 利用 Android Game Development Kit 将 ANR 发生率降低了 35%
《跑跑姜饼人:烤箱大逃亡》通过 Play Asset Delivery 节省了超过 20 万美元的 CDN 费用
新 STATE Mobile 利用 Android GPU 检查器将 GPU 使用量降低了 22%
《The Witcher: Monster Slayer》借助 Android Performance Tuner 扩大覆盖面
2K 借助 Play Asset Delivery 提供高清画质
“AGDE 简直太棒了!”;使用 Unreal Engine 进行 Android 开发
Firemonkeys 借助 AGDE 缩短了开发和调试时间
CD Projekt RED 借助 Play Asset Delivery 将游戏更新大小缩减了 90% 并将更新率提高了 10%
借助 Game Mode API,Gameloft 将设备功耗降低了 70%,从而使游戏时长延长了 35%
Gameloft 借助 Google Play Asset Delivery 将新用户数增加了 10%
RV AppStudios 借助 Google Play Asset Delivery 提高了用户留存率
Pixonic 针对大屏设备进行优化后,在 ChromeOS 上的互动度提高了 25%
Gameloft 针对 ChromeOS 进行优化后,收入迅速提升了 9 倍
Пока рекомендаций нет.
Попытайтесь войти в свой аккаунт Google.
В этом руководстве представлены лучшие практики и рекомендуемая архитектура для создания надежных и высококачественных приложений.
Пользовательский опыт мобильного приложения
Типичное приложение Android содержит несколько компонентов приложения , включая действия , фрагменты , службы , поставщиков контента и приемники широковещательных сообщений . Большинство этих компонентов приложения вы объявляете в манифесте приложения . Затем ОС Android использует этот файл, чтобы решить, как интегрировать ваше приложение в общий пользовательский интерфейс устройства. Учитывая, что типичное приложение Android может содержать несколько компонентов и что пользователи часто взаимодействуют с несколькими приложениями за короткий период времени, приложениям необходимо адаптироваться к различным типам рабочих процессов и задач, управляемых пользователем.
Имейте в виду, что мобильные устройства также ограничены в ресурсах, поэтому в любой момент операционная система может завершить некоторые процессы приложения, чтобы освободить место для новых.
Учитывая условия этой среды, компоненты вашего приложения могут запускаться индивидуально и не по порядку, и операционная система или пользователь могут уничтожить их в любой момент. Поскольку эти события не находятся под вашим контролем, вам не следует хранить или хранить в памяти какие-либо данные приложения или состояние в компонентах вашего приложения, а компоненты вашего приложения не должны зависеть друг от друга.
Общие архитектурные принципы
Если вам не следует использовать компоненты приложения для хранения данных и состояния приложения, как вместо этого вам следует спроектировать свое приложение?
Поскольку приложения Android растут в размерах, важно определить архитектуру, которая позволит приложению масштабироваться, повысит его надежность и упростит его тестирование.
Архитектура приложения определяет границы между частями приложения и обязанности, которые должна иметь каждая часть. Чтобы удовлетворить упомянутые выше потребности, вам следует спроектировать архитектуру своего приложения так, чтобы она следовала нескольким конкретным принципам.
Разделение интересов
Самый важный принцип, которому необходимо следовать, – это разделение задач . Распространенной ошибкой является запись всего кода в Activity
или Fragment
. Эти классы на основе пользовательского интерфейса должны содержать только логику, которая обрабатывает взаимодействие пользовательского интерфейса и операционной системы. Сохраняя эти классы как можно более компактными, вы можете избежать многих проблем, связанных с жизненным циклом компонентов, и улучшить тестируемость этих классов.
Имейте в виду, что у вас нет реализаций Activity
и Fragment
; скорее, это просто связующие классы, которые представляют собой контракт между ОС Android и вашим приложением. ОС может уничтожить их в любой момент в зависимости от взаимодействия с пользователем или из-за системных условий, таких как нехватка памяти. Чтобы обеспечить удовлетворительное взаимодействие с пользователем и более управляемое обслуживание приложений, лучше всего свести к минимуму вашу зависимость от них.
Управляйте пользовательским интерфейсом на основе моделей данных
Еще один важный принцип заключается в том, что вы должны создавать свой пользовательский интерфейс на основе моделей данных, предпочтительно постоянных моделей. Модели данных представляют данные приложения. Они независимы от элементов пользовательского интерфейса и других компонентов вашего приложения. Это означает, что они не привязаны к жизненному циклу пользовательского интерфейса и компонентов приложения, но все равно будут уничтожены, когда ОС решит удалить процесс приложения из памяти.
Стойкие модели идеальны по следующим причинам:
Ваши пользователи не потеряют данные, если ОС Android уничтожит ваше приложение, чтобы освободить ресурсы.
Ваше приложение продолжает работать в случаях, когда сетевое соединение нестабильно или недоступно.
Если вы основываете архитектуру своего приложения на классах модели данных, вы делаете свое приложение более тестируемым и надежным.
Единый источник истины
Когда в вашем приложении определен новый тип данных, вам следует назначить ему единый источник истины (SSOT). SSOT является владельцем этих данных, и только SSOT может их изменять или видоизменять. Для этого SSOT предоставляет данные с использованием неизменяемого типа, а для изменения данных SSOT предоставляет функции или получает события, которые могут вызывать другие типы.
Этот шаблон дает несколько преимуществ:
- Он централизует все изменения определенного типа данных в одном месте.
- Он защищает данные, чтобы другие типы не могли их подделать.
- Это делает изменения в данных более отслеживаемыми. Таким образом, ошибки легче обнаружить.
В автономном приложении источником достоверных данных обычно является база данных. В некоторых других случаях источником истины может быть ViewModel или даже пользовательский интерфейс.
Однонаправленный поток данных
Принцип единого источника истины часто используется в наших руководствах с шаблоном однонаправленного потока данных (UDF). В UDF состояние течет только в одном направлении. События , которые изменяют поток данных в противоположном направлении.
В Android состояние или данные обычно передаются из типов иерархии с более высокой областью действия в типы с более низкой областью действия. События обычно запускаются из типов с более низкой областью действия, пока не достигнут SSOT для соответствующего типа данных. Например, данные приложения обычно передаются из источников данных в пользовательский интерфейс. Пользовательские события, такие как нажатия кнопок, передаются из пользовательского интерфейса в SSOT, где данные приложения изменяются и предоставляются в неизменяемом типе.
Этот шаблон лучше гарантирует согласованность данных, менее подвержен ошибкам, его легче отлаживать и он использует все преимущества шаблона SSOT.
Рекомендуемая архитектура приложения
В этом разделе показано, как структурировать ваше приложение в соответствии с рекомендуемыми рекомендациями.
Учитывая общие архитектурные принципы, упомянутые в предыдущем разделе, каждое приложение должно иметь как минимум два уровня:
- Уровень пользовательского интерфейса , отображающий данные приложения на экране.
- Уровень данных , который содержит бизнес-логику вашего приложения и предоставляет данные приложения.
Вы можете добавить дополнительный уровень, называемый уровнем домена , чтобы упростить и повторно использовать взаимодействие между пользовательским интерфейсом и уровнями данных.

Современная архитектура приложений
Эта современная архитектура приложений поощряет использование, среди прочего, следующих методов:
- Реактивная и многоуровневая архитектура.
- Однонаправленный поток данных (UDF) на всех уровнях приложения.
- Уровень пользовательского интерфейса с держателями состояний для управления сложностью пользовательского интерфейса.
- Сопрограммы и потоки.
- Лучшие практики внедрения зависимостей.
Дополнительные сведения см. в следующих разделах, на других страницах «Архитектура» в оглавлении и на странице рекомендаций , содержащей сводку наиболее важных рекомендаций.
Уровень пользовательского интерфейса
Роль уровня пользовательского интерфейса (или уровня представления ) — отображение данных приложения на экране. Всякий раз, когда данные изменяются, либо из-за взаимодействия с пользователем (например, нажатия кнопки), либо из-за внешнего ввода (например, ответа сети), пользовательский интерфейс должен обновляться, чтобы отразить изменения.
Уровень пользовательского интерфейса состоит из двух вещей:
- Элементы пользовательского интерфейса, отображающие данные на экране. Вы создаете эти элементы с помощью функций Views или Jetpack Compose .
- Держатели состояний (такие как классы ViewModel ), которые содержат данные, предоставляют их пользовательскому интерфейсу и обрабатывают логику.

Дополнительные сведения об этом слое см. на странице «Слой пользовательского интерфейса» .
Уровень данных
Уровень данных приложения содержит бизнес-логику . Бизнес-логика — это то, что придает ценность вашему приложению: она состоит из правил, которые определяют, как ваше приложение создает, хранит и изменяет данные.
Уровень данных состоит из репозиториев , каждый из которых может содержать от нуля до многих источников данных . Вам следует создать класс репозитория для каждого типа данных, которые вы обрабатываете в своем приложении. Например, вы можете создать класс MoviesRepository
для данных, связанных с фильмами, или класс PaymentsRepository
для данных, связанных с платежами.

Классы репозитория отвечают за следующие задачи:
- Предоставление данных остальной части приложения.
- Централизация изменений в данных.
- Разрешение конфликтов между несколькими источниками данных.
- Абстрагирование источников данных от остальной части приложения.
- Содержит бизнес-логику.
Каждый класс источника данных должен нести ответственность за работу только с одним источником данных, которым может быть файл, сетевой источник или локальная база данных. Классы источников данных являются мостом между приложением и системой для операций с данными.
Дополнительную информацию об этом слое см. на странице уровня данных .
Слой домена
Уровень домена — это дополнительный уровень, который находится между уровнями пользовательского интерфейса и данных.
Уровень предметной области отвечает за инкапсуляцию сложной бизнес-логики или простой бизнес-логики, которая повторно используется несколькими моделями представления. Этот уровень является необязательным, поскольку не все приложения будут соответствовать этим требованиям. Его следует использовать только при необходимости — например, для решения сложных задач или для обеспечения возможности повторного использования.

Классы на этом уровне обычно называются вариантами использования или интеракторами . Каждый вариант использования должен нести ответственность за одну функциональность. Например, ваше приложение может иметь класс GetTimeZoneUseCase
, если несколько моделей ViewModel используют часовые пояса для отображения правильного сообщения на экране.
Чтобы узнать больше об этом слое, посетите страницу слоя домена .
Управление зависимостями между компонентами
Классы в вашем приложении зависят от других классов для правильной работы. Для сбора зависимостей определенного класса можно использовать любой из следующих шаблонов проектирования:
- Внедрение зависимостей (DI) . Внедрение зависимостей позволяет классам определять свои зависимости, не создавая их. Во время выполнения за предоставление этих зависимостей отвечает другой класс.
- Локатор сервисов : шаблон локатора сервисов предоставляет реестр, в котором классы могут получать свои зависимости, а не создавать их.
Эти шаблоны позволяют масштабировать ваш код, поскольку они предоставляют четкие шаблоны для управления зависимостями без дублирования кода и усложнения. Более того, эти шаблоны позволяют быстро переключаться между тестовой и производственной реализациями.
Мы рекомендуем следовать шаблонам внедрения зависимостей и использовать библиотеку Hilt в приложениях Android. Hilt автоматически конструирует объекты, проходя по дереву зависимостей, предоставляет гарантии времени компиляции для зависимостей и создает контейнеры зависимостей для классов платформы Android.
Общие рекомендации
Программирование — творческая область, и создание приложений для Android — не исключение. Есть много способов решить проблему; вы можете передавать данные между несколькими действиями или фрагментами, получать удаленные данные и сохранять их локально для автономного режима или обрабатывать любое количество других распространенных сценариев, с которыми сталкиваются нетривиальные приложения.
Хотя следующие рекомендации не являются обязательными, в большинстве случаев их следование делает вашу кодовую базу более надежной, тестируемой и поддерживаемой в долгосрочной перспективе:
Не храните данные в компонентах приложения.
Не назначайте точки входа вашего приложения, такие как действия, службы и приемники вещания, в качестве источников данных. Вместо этого им следует координировать свои действия только с другими компонентами для получения подмножества данных, имеющих отношение к этой точке входа. Срок службы каждого компонента приложения довольно недолговечен, в зависимости от взаимодействия пользователя со своим устройством и общего текущего состояния системы.
Уменьшите зависимости от классов Android.
Компоненты вашего приложения должны быть единственными классами, которые полагаются на API-интерфейсы SDK платформы Android, такие как Context
или Toast
. Отделение от них других классов в вашем приложении помогает улучшить тестируемость и уменьшает связанность внутри вашего приложения.
Создайте четко определенные границы ответственности между различными модулями вашего приложения.
Например, не распространяйте код, загружающий данные из сети, на несколько классов или пакетов в вашей кодовой базе. Аналогичным образом, не определяйте несколько несвязанных обязанностей, таких как кэширование данных и привязка данных, в одном классе. Следование рекомендуемой архитектуре приложения поможет вам в этом.
Как можно меньше подвергайте воздействию каждого модуля.
Например, не поддавайтесь искушению создать ярлык, раскрывающий детали внутренней реализации модуля. В краткосрочной перспективе вы можете выиграть немного времени, но тогда вы, скорее всего, многократно столкнетесь с техническим долгом по мере развития вашей кодовой базы.
Сосредоточьтесь на уникальности своего приложения, чтобы оно выделялось среди других приложений.
Не изобретайте велосипед, снова и снова написав один и тот же шаблонный код. Вместо этого сосредоточьте свое время и силы на том, что делает ваше приложение уникальным, и позвольте библиотекам Jetpack и другим рекомендуемым библиотекам справиться с повторяющимся шаблоном.
Подумайте, как сделать каждую часть вашего приложения тестируемой по отдельности.
Например, наличие четко определенного API для получения данных из сети упрощает тестирование модуля, который сохраняет эти данные в локальной базе данных. Если вместо этого вы смешаете логику этих двух модулей в одном месте или распределите сетевой код по всей базе кода, эффективное тестирование станет гораздо сложнее, если вообще возможно.
Типы отвечают за свою политику параллелизма.
Если тип выполняет длительную блокирующую работу, он должен нести ответственность за перемещение этих вычислений в правильный поток. Этот конкретный тип знает тип вычислений, которые он выполняет, и в каком потоке они должны выполняться. Типы должны быть безопасными для основного потока, то есть их можно безопасно вызывать из основного потока, не блокируя его.
Сохраняйте как можно больше актуальных и свежих данных.
Таким образом, пользователи смогут пользоваться функциями вашего приложения, даже если их устройство находится в автономном режиме. Помните, что не всем вашим пользователям нравится постоянное высокоскоростное соединение, а даже если и они это делают, они могут получить плохой сигнал в людных местах.
Преимущества архитектуры
Наличие хорошей архитектуры в вашем приложении приносит много преимуществ проектным и инженерным группам:
- Это улучшает удобство обслуживания, качество и надежность всего приложения.
- Это позволяет приложению масштабироваться. Больше людей и больше команд могут вносить свой вклад в одну и ту же базу кода с минимальными конфликтами кода.
- Это помогает при адаптации. Поскольку архитектура обеспечивает согласованность вашего проекта, новые члены команды могут быстро освоиться и работать более эффективно за меньшее время.
- Это легче протестировать. Хорошая архитектура поощряет более простые типы, которые, как правило, легче тестировать.
- Ошибки можно исследовать методически с помощью четко определенных процессов.
Инвестиции в архитектуру также оказывают прямое влияние на ваших пользователей. Они получают выгоду от более стабильного приложения и большего количества функций благодаря более продуктивной команде инженеров. Однако архитектура также требует первоначальных вложений времени. Чтобы помочь вам оправдать это время для остальной части вашей компании, взгляните на эти тематические исследования , где другие компании делятся своими историями успеха, когда в своем приложении есть хорошая архитектура.
Образцы
Следующие образцы Google демонстрируют хорошую архитектуру приложения. Иди исследуйте их, чтобы увидеть это руководство на практике:
Mir 2: Return of the King 是 Actoz Soft 授权的优质《传奇》IP 移动游戏,由 HK ZHILI YAOAN LIMITED 使用 Unity 游戏引擎开发。 这款游戏不仅完美再现了韩国奇幻类 MMORPG 的代表作 Mir 2 的游戏氛围,还提供了许多最受欢迎的游戏内容,例如装备收集、大规模沙漠攻击和其他核心玩法。 该游戏使用了 Android Frame Pacing 库 (Swappy) 来提高帧速率的稳定性、实现流畅的渲染,并显著提升了 Android 鸣潮 是一款由 Kuro Games 开发的高保真动作角色扮演游戏。为了持续为长时间的游戏会话提供卓越的用户体验,优化功耗非常重要。 Android Studio 从 Hedgehog (2023.1.1) 开始引入了 功耗性能分析器 ,可帮助开发者根据设备端电源轨监视器 (ODPM) 了解功耗数据。 借助 Android Studio 中的功耗性能分析功能,您还可以 有效地对 Android 应用功能的功耗进行 A/B 测试 (如下所示)。 Kuro Games 首先使用 Android Godot Engine 是一个广受欢迎的多平台开源游戏引擎,对 Android 提供强大的支持。Godot 可用于制作几乎任何类型的游戏,并且支持 2D 和 3D 图形。Godot 4 版引入了新的渲染系统,该系统具有用于高保真图形的高级功能。Godot 4 渲染程序专为 Vulkan 等现代图形 API 而设计。 Godot Foundation 聘请了 The Forge Interactive 的图形优化专家,并与 Google 合作分析和进一步改进了 Godot 4 Vulkan Android 动态性能框架 (ADPF) 是 Google 推出的一款强大工具,适用于希望优化应用性能的开发者。ADPF 通过其热管理 API 提供有关设备热状态的实时信息,这些信息随后用于调整应用中的图形设置。 出于研究目的,Arm 使用 Unreal Engine 和 ADPF 开发了一个演示版,以研究如何使用 ADPF 优化游戏性能。 ADPF 会监控热状态,并相应地在游戏引擎中调整图形质量。 NCSoft《天堂 W》是由 NCSoft 开发的大型多人在线角色扮演游戏 (MMORPG)。这款游戏继承了原始 Lineage W 游戏的传统,为世界各地的玩家提供了一个环境,让他们可以通过全球服务器进行合作和竞争。《Lineage W》以独特的中世纪奇幻世界为背景,通过各种职业、技能和战斗系统为玩家提供深层次的游戏体验。 NCSoft 使用 Android 动态性能框架最大限度地提高了图形质量,同时避免了由温控调频导致的性能问题。 Android 动态性能框架 (ADPF) 改进性能和散热管理对于开发成功的 Android 游戏至关重要。传统上,开发者必须通过降低游戏保真度或进一步优化渲染程序来管理这些问题。这些更改往往针对特定游戏,并且往往不够灵活。 Android 生态系统中的多个参与者为开发者提供了自适应性能 API。为了简化自适应性能功能的集成并减少生态系统中的碎片化,Google 和 MediaTek 携手合作集成了我们的产品:Android 动态性能框架 (ADPF) 和 MediaTek 自适应游戏技术 (MAGT)。 借助 ADPF 使命召唤:战争地带移动版 是广受欢迎的《使命召唤》系列中的第一人称动作游戏。 超受欢迎的主机和 PC 游戏的移动实现利用低层级移动 API 来提供出色的玩家体验。 从技术角度来看,移动实现的目标是支持各种 Android 移动设备,同时尽可能使实现与主机版本保持一致,并确保图形管道和工具链与当前的主机和 PC 游戏及内容保持兼容。 Call of Duty 引擎使用名为 任务图渲染程序 的系统实现渲染提交管理的同步、内存分配和调度,该系统确定在 GPU 《魔灵召唤:克罗尼柯战记》 是韩国游戏开发商 Com2uS 于 2023 年 3 月面向全球发布的一款移动端大型多人在线角色扮演游戏。迄今为止,《魔灵召唤》在全球的下载量超过 1.8 亿,收入超过 27 亿美元。《魔灵召唤》是目前全球最受欢迎的手游之一,这款游戏展现了一个奇幻世界,玩家必须收集并训练各种怪物,才能与其他玩家对战。 近十年过去了,这款游戏庞大的玩家社区依然很是活跃,而且仍在扩展,部分原因在于 Com2uS 不断发布新的内容和更新,使这款游戏历久弥新、十分刺激。Com2uS 《魔灵召唤:克罗尼柯战记》 US(WW) 和 KR by Com2uS 专门利用 Vulkan 在 Android 上进行渲染,可将性能提升高达 30%。 Vulkan 是一种现代化的跨平台 3D 图形 API,旨在最大限度减少设备图形硬件与您的游戏之间的抽象。与 OpenGL ES 相比,Vulkan 的 CPU 开销更低,并且 Vulkan 提供更广泛的功能。 Com2uS 为 《魔灵召唤:克罗尼柯战记》 开发了高级渲染功能,包括: 《魔灵召唤:克罗尼柯战记》 对 Android 《Ares: Rise of Guardians 》是一款移动设备转 PC 的科幻 MMORPG 游戏,由 Second Dive 开发,后者是一家位于韩国的游戏工作室,以其动作角色扮演系列开发方面的专业知识而闻名。该游戏由 Kakao Games 发布。 《阿瑞斯》以广袤的宇宙为背景,采用细节满满的未来主义背景。《阿瑞斯》充满了刺激的玩法和画面精美的角色,涉及身着战斗服的战斗人员。然而,由于这些细节丰富的图形,一些用户的设备在处理游戏内容时有些吃力。 Cat Daddy Games 是一家全资 2K 工作室,位于华盛顿州柯克兰,是 NBA 2K Mobile 的开发者。该团队希望提高游戏的整体质量和稳定性,具体方法是减少“应用无响应”错误 (ANR)。如果 Android 应用的界面线程处于阻塞状态的时间过长,就会发生 ANR。发生这种情况时,负责更新界面的应用主线程将无法绘制或处理用户输入事件,这会引起用户的不满。如果应用在前台运行,系统会显示一个对话框,允许用户强制退出应用。 减少 ANR 一直是 Cat Daddy 的首要任务。QA Devsisters 是一家全球性的移动游戏开发商和发布商,专门制作基于《跑跑姜饼人》IP 的休闲游戏。他们最受欢迎的游戏包括 《跑跑姜饼人:烤箱大逃亡》 (跑步街机)和 《跑跑王国》 (社交 RPG),这两款游戏都深受全球用户的喜爱,尤其是在韩国、台湾和美国。虽然《跑跑姜饼人:烤箱大逃亡》是一款休闲游戏,但五年积累的资源使 CDN 容量提高到了 2.5GB,这使得 CDN 费用的增加。Devsisters 需要找到一种可持续的模式来宣传他们的大文件游戏。 Devsisters 发现,大量的 NEW STATE Mobile 是 Krafton 的一款大逃杀游戏于 2021 年 11 月面向全球发布,在发布后的第一个月便获得了超过 4500 万次下载。KRAFTON, Inc. 是一个由多个独立的游戏开发工作室组成的联合公司,旨在为全球游戏玩家打造富有吸引力的创新娱乐体验。该公司包括 PUBG Studio、Bluehole Studio、Striking Distance Studio、RisingWings、Dreamotion 和 Unknown Spokko 住在波兰,是一群雄心勃勃的创作者,他们致力于打造要求极为严苛的 IP。Spokko 是 CD PROJEKT 家族的成员,但是一家独立公司,已将 《巫师:怪物杀手》 的精彩世界转移到智能手机上。 《巫师:怪物杀手》是一款使用增强现实技术的基于位置的角色扮演游戏。这是一款计算密集型游戏,会给许多设备带来挑战。发布之初,Spokko 希望确保其游戏可以覆盖尽可能多的用户,同时为所有人提供高品质的体验。 Cat Daddy Games 是一家全资 2K 工作室,总部位于华盛顿州柯克兰。NBA 2K Mobile、NBA SuperCard 和 WWE SuperCard 系列背后的团队正在寻找一个解决方案来为用户提高游戏的整体质量,具体方法是在支持这些游戏的设备上提供更优质的素材资源。 他们实现了 Play Asset Delivery,以简单而更灵活的方式针对每位用户的设备配置生成并提供经过优化的 APK,并使用纹理压缩格式定位功能针对特定设备提供更好的美术资源并减少资源下载。 首先,Cat Unreal Engine 是由 Epic Games 开发的游戏引擎,可为各行各业的创作者提供自由和控制权,让他们提供先进的娱乐、富有吸引力的可视化内容和沉浸式虚拟世界。一些主要的 Android 游戏都是使用 Unreal Engine 构建的。 图 1. 在 Pixel 4 上运行的 Unreal Engine Suntemple 示例的屏幕截图 Epic 和其他游戏开发者使用 Android Studio 调试 C++、Kotlin 或 Java 编程语言,但许多游戏开发者都有以 Electronic Arts (EA) 是一家总部位于美国加利福尼亚州的游戏公司。它制作了各种不同类型的游戏,例如体育、动作、赛车和模拟游戏。EA 的开发工作室 Firemonkeys 因开发 真实赛车 3 、 模拟人生自由玩 和 Need For Speed: No Limits 而闻名于世。Firemonkeys 使用自定义游戏引擎来开发游戏,现在他们的所有 Android 游戏都在其开发工作流中使用 Android Game Development Extension (AGDE) 游戏开发商 CD Projekt RED (CDPR) 位于波兰华沙,他们重新构思了自己的迷你游戏《巫师 3》、 《巫师之昆特牌》 ,并于 2020 年 3 月在 Google Play 上以独立的免费畅玩形式发布。由于初始文件较大,且定期更新需要额外的设备存储空间,用户通常必须重新安装完整版游戏,才能获得更新的版本。这是游戏社区中最突出的挫败点。为了帮助进行差分修补,CDPR 通过实现 Play Asset Delivery 取得了巨大的成功。 CDPR 是实现 Play Asset 20 多年来, Gameloft 为数字平台打造了富有创意的游戏体验,从移动游戏到跨平台 PC 和主机游戏,不一而足。除了自有的知名游戏系列外,Gameloft 还为乐高、环球和长宝等热门品牌开发游戏。他们的游戏团队在全球拥有 3,600 名员工,每月可在 100 多个国家/地区覆盖 5500 万唯一身份玩家。 竞速街机游戏 Asphalt 9: Legends 于 2018 年首次发布,他们需要找到一种平衡性能、保真度和电池的方式。为此,Gameloft 怀着对游戏的热情以及将游戏带给世界各地玩家的渴望, Gameloft 于 2000 年成立。他们是开发移动游戏的先驱,现在旗下有超过 190 款游戏。Gameloft 的许多移动游戏是图形密集型游戏,下载大小较大。这使得他们成为 Google Play Asset Delivery (PAD) 早期开发阶段一个极具吸引力的合作伙伴。PAD 是一套基于我们的 app bundle 基础架构构建的游戏服务分发功能。PAD 会在适当的时间免费向适当的设备提供免费、动态的适当游戏素材资源。这引起了 RV AppStudios 是一家总部位于美国的游戏开发商,该公司旗下的休闲游戏、教育儿童应用和实用类应用到目前为止已有超过 2 亿的下载量。该团队在其应用 Puzzle Kids - Animals Shapes and Jigsaw Puzzles 中引入了 Google Play Asset Delivery,属于早期测试用户。他们希望优化应用的大小,节省资金,并在需要下载新的资源包时消除任何干扰,从而提升用户体验。 当用户安装 Puzzle Kids Pixonic 是一个总部位于莫斯科的视频游戏开发团队,其以抓住每一个机会升级自己的移动应用并覆盖更广泛的玩家群体为荣。该公司最著名的游戏之一是 《War Robots》 ,这是一款 12 人的玩家对战 (PVP) 游戏,玩家可以在即时战场上操作定制的机器人进行决斗。 《War Robots》于 2014 年发布,最初是专为 Android 的早期设备设计的,通过触控板操控游戏角色,用不到鼠标。Pixonic Gameloft 一直致力于成为首批在最新便携式硬件上发布游戏的开发商之一,以便随时随地为玩家提供激动人心的体验。因此,Gameloft 知道 ChromeOS 是适合其移动赛车系列最新游戏《狂野飙车 8:极速凌云》的平台。 Gameloft 非常了解如何针对不同的设备开发游戏,但将 Asphalt 体验转换为 Chromebook 特有的触摸屏/键盘混合控制(可随时切换)似乎具有挑战性。然而,结果证明这个过程没有想象的那么困难,值得一试。 利用 ChromebookMir 2 通过使用 Frame Pacing 库来提升渲染性能
Kuro Games 使用 Android Studio 功耗性能分析器和 ODPM 为 Wuthering Waves 降低了 9.68% 的功耗
适用于 Android 的 Godot Engine Vulkan 优化
在 Unreal Engine 中使用 Android 动态性能框架 (ADPF) 入门
NCSoft Lineage W 使用 ADPF 提高了持续性能并防止温控降频
MediaTek 提升了 Android SoC 的动态性能
《使命召唤:战争地带手游》使用 Vulkan 提升图形效果
Com2uS - Google Play 游戏电脑版
Com2uS 使用 Vulkan 提升图形效果
Kakao Games 通过 Android 自适应功能将 FPS 稳定性提升至 96%
2K 利用 Android Game Development Kit 将 ANR 发生率降低了 35%
《跑跑姜饼人:烤箱大逃亡》通过 Play Asset Delivery 节省了超过 20 万美元的 CDN 费用
新 STATE Mobile 利用 Android GPU 检查器将 GPU 使用量降低了 22%
《The Witcher: Monster Slayer》借助 Android Performance Tuner 扩大覆盖面
2K 借助 Play Asset Delivery 提供高清画质
“AGDE 简直太棒了!”;使用 Unreal Engine 进行 Android 开发
Firemonkeys 借助 AGDE 缩短了开发和调试时间
CD Projekt RED 借助 Play Asset Delivery 将游戏更新大小缩减了 90% 并将更新率提高了 10%
借助 Game Mode API,Gameloft 将设备功耗降低了 70%,从而使游戏时长延长了 35%
Gameloft 借助 Google Play Asset Delivery 将新用户数增加了 10%
RV AppStudios 借助 Google Play Asset Delivery 提高了用户留存率
Pixonic 针对大屏设备进行优化后,在 ChromeOS 上的互动度提高了 25%
Gameloft 针对 ChromeOS 进行优化后,收入迅速提升了 9 倍
Пока рекомендаций нет.
Попытайтесь войти в свой аккаунт Google.
Это руководство охватывает лучшие практики и рекомендуется архитектуру для создания надежных высококачественных приложений.
Опыт пользователей мобильного приложения
Типичное приложение для Android содержит несколько компонентов приложения , включая действия , фрагменты , услуги , поставщики контента и вещательные приемники . Вы объявляете большинство этих компонентов приложения в своем манифесте приложения . Затем ОС Android использует этот файл, чтобы решить, как интегрировать ваше приложение в общий пользовательский опыт устройства. Учитывая, что типичное приложение для Android может содержать несколько компонентов и что пользователи часто взаимодействуют с несколькими приложениями за короткий период времени, приложения должны адаптироваться к различным видам рабочих процессов и задач, управляемых пользователями.
Имейте в виду, что мобильные устройства также ограничены ресурсами, поэтому в любое время операционная система может убить некоторые процессы приложений, чтобы освободить место для новых.
Учитывая условия этой среды, можно запустить компоненты вашего приложения индивидуально и вне порядка, а операционная система или пользователь могут уничтожить их в любое время. Поскольку эти события не находятся под вашим контролем, вы не должны хранить или хранить в памяти какие -либо данные приложения или состояние в компонентах вашего приложения, а компоненты вашего приложения не должны зависеть друг от друга.
Общие архитектурные принципы
Если вы не используете компоненты приложения для хранения данных и состояния приложений, как вы должны разрабатывать ваше приложение?
По мере того, как приложения Android растут в размерах, важно определить архитектуру, которая позволяет приложению масштабироваться, увеличивает надежность приложения и облегчает тестирование приложения.
Архитектура приложения определяет границы между частями приложения и обязанностями, которую должна иметь каждая часть. Чтобы удовлетворить упомянутые выше потребности, вы должны разработать архитектуру приложения, чтобы следовать нескольким конкретным принципам.
Разделение проблем
Наиболее важным принципом является разделение проблем . Это обычная ошибка - написать весь свой код в Activity
или Fragment
. Эти классы на основе пользовательского интерфейса должны содержать только логику, которая обрабатывает пользовательский интерфейс и взаимодействие операционной системы. Поддерживая эти классы максимально наклоненными, вы можете избежать многих проблем, связанных с жизненным циклом компонента, и улучшить тестируемость этих классов.
Имейте в виду, что у вас нет реализации Activity
и Fragment
; Скорее, это просто классы клея, которые представляют контракт между ОС Android и вашим приложением. ОС может уничтожить их в любое время на основе взаимодействия с пользователями или из -за таких системных условий, как низкая память. Чтобы обеспечить удовлетворительный пользовательский опыт и более управляемый опыт обслуживания приложений, лучше всего минимизировать вашу зависимость от них.
Привести пользовательский интерфейс из моделей данных
Другим важным принципом является то, что вы должны управлять своим пользовательским интерфейсом из моделей данных, предпочтительно постоянных моделей. Модели данных представляют данные приложения. Они независимы от элементов пользовательского интерфейса и других компонентов в вашем приложении. Это означает, что они не привязаны к жизненному циклу компонента пользовательского интерфейса и приложения, но все равно будут уничтожены, когда ОС решает удалить процесс приложения из памяти.
Постоянные модели идеально подходят для следующих причин:
Ваши пользователи не теряют данные, если ОС Android разрушает ваше приложение, чтобы освободить ресурсы.
Ваше приложение продолжает работать в тех случаях, когда сетевое соединение является ловким или недоступным.
Если вы основываете архитектуру приложения на классах модели данных, вы сделаете ваше приложение более тестируемым и надежным.
Единственный источник истины
Когда в вашем приложении определяется новый тип данных, вы должны присвоить ему один источник истины (SSOT). SSOT является владельцем этих данных, и только SSOT может изменять или мутировать. Чтобы достичь этого, SSOT раскрывает данные с использованием неизменного типа, и для модификации данных SSOT раскрывает функции или получает события, которые могут вызвать другие типы.
Этот шаблон приносит несколько преимуществ:
- Он централизует все изменения в определенном типе данных в одном месте.
- Он защищает данные, чтобы другие типы не могли вмешиваться в них.
- Это вносит изменения в данные более отслеживаемыми. Таким образом, ошибки легче определить.
В приложении в автономном режиме источником истины для данных приложения обычно является база данных. В некоторых других случаях источником истины может быть ViewModel или даже пользовательский интерфейс.
Однонаправленный поток данных
Один источник принципа истины часто используется в наших руководствах с шаблоном однонаправленного потока данных (UDF). В UDF государство течет только в одном направлении. События , которые изменяют поток данных в противоположном направлении.
В Android, состояние или данные обычно проходят от более высоких типов иерархии к более низким. События обычно запускаются из типов с более низким содержанием до тех пор, пока они не достигнут SSOT для соответствующего типа данных. Например, данные приложения обычно тещают из источников данных в пользовательский интерфейс. Пользовательские события, такие как нажатие кнопки, нажатие от пользовательского интерфейса к SSOT, где данные приложения изменяются и выявляются в неизменном типе.
Эта модель лучше гарантирует согласованность данных, менее склонна к ошибкам, легче отлаживать и приносит все преимущества схемы SSOT.
Рекомендуемая архитектура приложения
Этот раздел демонстрирует, как структурировать ваше приложение после рекомендуемых лучших практик.
Учитывая общие архитектурные принципы, упомянутые в предыдущем разделе, каждое приложение должно иметь как минимум два уровня:
- Уровень пользовательского интерфейса , который отображает данные приложения на экране.
- Уровень данных , который содержит бизнес -логику вашего приложения и раскрывает данные приложения.
Вы можете добавить дополнительный слой, называемый доменным слоем , чтобы упростить и повторно использовать взаимодействие между пользовательским интерфейсом и уровнями данных.

Современная архитектура приложения
Эта современная архитектура приложения поощряет использование следующих методов, среди прочего:
- Реактивная и многослойная архитектура.
- Однонаправленный поток данных (UDF) во всех уровнях приложения.
- Уровень пользовательского интерфейса с государственными держателями для управления сложностью пользовательского интерфейса.
- Краутины и потоки.
- Лучшие практики впрыскивания зависимости.
Для получения дополнительной информации см. Следующие разделы, другие страницы архитектуры в содержимого и страницу рекомендаций , на которой содержится краткое изложение наиболее важных лучших практик.
Ui слой
Роль слоя пользовательского интерфейса (или презентационного уровня ) состоит в том, чтобы отобразить данные приложения на экране. Всякий раз, когда данные меняются, либо из -за взаимодействия с пользователем (например, нажатия кнопки) или внешнего ввода (например, сетевого ответа), пользовательский интерфейс должен обновляться, чтобы отразить изменения.
Слой пользовательского интерфейса состоит из двух вещей:
- Элементы пользовательского интерфейса, которые отображают данные на экране. Вы создаете эти элементы, используя виды или функции JetPack .
- Государственные держатели (такие как классы ViewModel ), которые содержат данные, подвергают их пользовательскому интерфейсу и обрабатывают логику.

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

Занятия репозитория отвечают за следующие задачи:
- Разоблачение данных остальной части приложения.
- Централизация изменений в данных.
- Решение конфликтов между несколькими источниками данных.
- Абстрагирование источников данных из остальной части приложения.
- Содержащая бизнес -логику.
Каждый класс источника данных должен нести ответственность за работу только с одним источником данных, который может быть файлом, сетевым источником или локальной базой данных. Классы источника данных - это мост между приложением и системой для операций данных.
Чтобы узнать больше об этом уровне, см. Страницу уровня данных .
Домен слой
Доменный слой - это необязательный слой, который находится между пользовательским интерфейсом и уровнями данных.
Доменный уровень отвечает за инкапсуляцию сложной бизнес -логики или простую бизнес -логику, которая повторно используется несколькими видами. Этот слой не является обязательным, потому что не все приложения будут иметь эти требования. Вы должны использовать его только при необходимости - например, для обработки сложности или в пользу повторного использования.

Классы в этом слое обычно называют вариантами использования или взаимодействиями . Каждый вариант использования должен нести ответственность за одну функциональность. Например, ваше приложение может иметь класс GetTimeZoneUseCase
, если несколько просмотров полагаются на часовые пояса, чтобы отобразить правильное сообщение на экране.
Чтобы узнать больше об этом слое, см. Страницу домена .
Управлять зависимостями между компонентами
Занятия в вашем приложении зависят от других классов, чтобы функционировать должным образом. Вы можете использовать любой из следующих шаблонов дизайна для сбора зависимостей определенного класса:
- Инъекция зависимости (DI) : инъекция зависимости позволяет классам определять свои зависимости, не построив их. Во время выполнения, другой класс отвечает за обеспечение этих зависимостей.
- Локатор обслуживания : шаблон локатора обслуживания предоставляет реестр, в котором классы могут получить свои зависимости вместо их построения.
Эти шаблоны позволяют вам масштабировать ваш код, потому что они предоставляют четкие шаблоны для управления зависимостями без дублирования кода или добавления сложности. Кроме того, эти модели позволяют быстро переключаться между тестовыми и производственными реализациями.
Мы рекомендуем следить за шаблонами впрыска зависимостей и использовать библиотеку рукояти в приложениях Android. Хилт автоматически строит объекты, ходя по дереву зависимости, обеспечивает гарантии времени компиляции на зависимости и создает контейнеры зависимости для классов Android Framework.
Общие лучшие практики
Программирование - это креативная область, а создание приложений Android не является исключением. Есть много способов решить проблему; Вы можете передавать данные между несколькими действиями или фрагментами, извлекать удаленные данные и сохранять их локально для автономного режима или обрабатывать любое количество других общих сценариев, с которыми сталкиваются нетривиальные приложения.
Хотя следующие рекомендации не являются обязательными, в большинстве случаев, следующих за ними, делает вашу базу кода более надежной, тестируемой и обслуживаемой в долгосрочной перспективе:
Не храните данные в компонентах приложения.
Избегайте назначения точек входа вашего приложения, таких как действия, услуги и вещательные приемники - как источники данных. Вместо этого они должны координировать только с другими компонентами для извлечения подмножества данных, имеющих отношение к этой точке входа. Каждый компонент приложения довольно недолговечен, в зависимости от взаимодействия пользователя с их устройством и общего текущего здоровья системы.
Уменьшить зависимости от классов Android.
Компоненты вашего приложения должны быть единственными классами, которые полагаются на API API Android Framework SDK, такие как Context
или Toast
. Абстракция других классов в вашем приложении от них помогает с тестируемостью и уменьшает связь в вашем приложении.
Создайте четко определенные границы ответственности между различными модулями в вашем приложении.
Например, не распространяйте код, который загружает данные из сети по нескольким классам или пакетам в вашей базе кода. Точно так же не определяйте множество несвязанных обязанностей, таких как кэширование данных и привязка данных, в том же классе. После рекомендуемой архитектуры приложения вам это поможет.
Разоблачить как можно меньше от каждого модуля.
Например, не испытывайте искушения создать ярлык, который раскрывает детали внутренней реализации из модуля. Вы можете получить немного времени в краткосрочной перспективе, но тогда вы, вероятно, будете нести технический долг много раз по мере развития вашей кодовой базы.
Сосредоточьтесь на уникальном ядре вашего приложения, чтобы он выделялся из других приложений.
Не заново переосмыслить колесо, снова и снова написав тот же код шаблона. Вместо этого сосредоточьтесь на своем времени и энергии на том, что делает ваше приложение уникальным, и пусть библиотеки JetPack и другие рекомендуемые библиотеки обрабатывают повторяющуюся пакет.
Подумайте, как сделать каждую часть вашего приложения тестировать в изоляции.
Например, наличие четко определенного API для извлечения данных из сети облегчает тестирование модуля, который сохраняет эти данные в локальной базе данных. Если вместо этого вы смешиваете логику из этих двух модулей в одном месте или распространяете свой сетевой код по всей вашей базе кода, становится гораздо сложнее - если невозможно - тестировать эффективно.
Типы отвечают за их политику параллелистики.
Если тип выполняет долгосрочную блокирующую работу, он должен отвечать за перемещение этого вычисления в правильный поток. Этот конкретный тип знает тип вычислений, который он делает и в каком потоке он должен быть выполнен. Типы должны быть основными, что означает, что они безопасны для вызова из основного потока, не блокируя его.
Сохраняется как можно более актуальные и свежие данные.
Таким образом, пользователи могут наслаждаться функциональностью вашего приложения, даже если их устройство находится в автономном режиме. Помните, что не все ваши пользователи получают постоянное, высокоскоростное соединение-и даже если они это сделают, они могут получить плохой прием в многолюдных местах.
Преимущества архитектуры
Применение хорошей архитектуры в вашем приложении приносит много преимуществ для проектных и инженерных команд:
- Это улучшает обслуживание, качество и надежность общего приложения.
- Это позволяет приложению масштабироваться. Больше людей и больше команд могут внести свой вклад в одну и ту же кодовую базу с минимальными конфликтами кода.
- Это помогает при внедрении. Поскольку архитектура привносит согласованность в ваш проект, новые члены команды могут быстро подняться до скорости и быть более эффективными за меньшее время.
- Это легче проверить. Хорошая архитектура поощряет более простые типы, которые, как правило, легче тестировать.
- Ошибки можно исследовать методично с четко определенными процессами.
Инвестирование в архитектуру также оказывает прямое влияние на ваших пользователей. Они извлекают выгоду из более стабильного применения и большего количества функций благодаря более продуктивной команде инженеров. Тем не менее, архитектура также требует передовых инвестиций. Чтобы помочь вам оправдать это время для остальной части вашей компании, взгляните на эти тематические исследования , где другие компании делятся своими историями успеха, когда в своем приложении есть хорошая архитектура.
Образцы
Следующие образцы Google демонстрируют хорошую архитектуру приложения. Иди исследуйте их, чтобы увидеть это руководство на практике:
Mir 2: Return of the King 是 Actoz Soft 授权的优质《传奇》IP 移动游戏,由 HK ZHILI YAOAN LIMITED 使用 Unity 游戏引擎开发。 这款游戏不仅完美再现了韩国奇幻类 MMORPG 的代表作 Mir 2 的游戏氛围,还提供了许多最受欢迎的游戏内容,例如装备收集、大规模沙漠攻击和其他核心玩法。 该游戏使用了 Android Frame Pacing 库 (Swappy) 来提高帧速率的稳定性、实现流畅的渲染,并显著提升了 Android 鸣潮 是一款由 Kuro Games 开发的高保真动作角色扮演游戏。为了持续为长时间的游戏会话提供卓越的用户体验,优化功耗非常重要。 Android Studio 从 Hedgehog (2023.1.1) 开始引入了 功耗性能分析器 ,可帮助开发者根据设备端电源轨监视器 (ODPM) 了解功耗数据。 借助 Android Studio 中的功耗性能分析功能,您还可以 有效地对 Android 应用功能的功耗进行 A/B 测试 (如下所示)。 Kuro Games 首先使用 Android Godot Engine 是一个广受欢迎的多平台开源游戏引擎,对 Android 提供强大的支持。Godot 可用于制作几乎任何类型的游戏,并且支持 2D 和 3D 图形。Godot 4 版引入了新的渲染系统,该系统具有用于高保真图形的高级功能。Godot 4 渲染程序专为 Vulkan 等现代图形 API 而设计。 Godot Foundation 聘请了 The Forge Interactive 的图形优化专家,并与 Google 合作分析和进一步改进了 Godot 4 Vulkan Android 动态性能框架 (ADPF) 是 Google 推出的一款强大工具,适用于希望优化应用性能的开发者。ADPF 通过其热管理 API 提供有关设备热状态的实时信息,这些信息随后用于调整应用中的图形设置。 出于研究目的,Arm 使用 Unreal Engine 和 ADPF 开发了一个演示版,以研究如何使用 ADPF 优化游戏性能。 ADPF 会监控热状态,并相应地在游戏引擎中调整图形质量。 NCSoft《天堂 W》是由 NCSoft 开发的大型多人在线角色扮演游戏 (MMORPG)。这款游戏继承了原始 Lineage W 游戏的传统,为世界各地的玩家提供了一个环境,让他们可以通过全球服务器进行合作和竞争。《Lineage W》以独特的中世纪奇幻世界为背景,通过各种职业、技能和战斗系统为玩家提供深层次的游戏体验。 NCSoft 使用 Android 动态性能框架最大限度地提高了图形质量,同时避免了由温控调频导致的性能问题。 Android 动态性能框架 (ADPF) 改进性能和散热管理对于开发成功的 Android 游戏至关重要。传统上,开发者必须通过降低游戏保真度或进一步优化渲染程序来管理这些问题。这些更改往往针对特定游戏,并且往往不够灵活。 Android 生态系统中的多个参与者为开发者提供了自适应性能 API。为了简化自适应性能功能的集成并减少生态系统中的碎片化,Google 和 MediaTek 携手合作集成了我们的产品:Android 动态性能框架 (ADPF) 和 MediaTek 自适应游戏技术 (MAGT)。 借助 ADPF 使命召唤:战争地带移动版 是广受欢迎的《使命召唤》系列中的第一人称动作游戏。 超受欢迎的主机和 PC 游戏的移动实现利用低层级移动 API 来提供出色的玩家体验。 从技术角度来看,移动实现的目标是支持各种 Android 移动设备,同时尽可能使实现与主机版本保持一致,并确保图形管道和工具链与当前的主机和 PC 游戏及内容保持兼容。 Call of Duty 引擎使用名为 任务图渲染程序 的系统实现渲染提交管理的同步、内存分配和调度,该系统确定在 GPU 《魔灵召唤:克罗尼柯战记》 是韩国游戏开发商 Com2uS 于 2023 年 3 月面向全球发布的一款移动端大型多人在线角色扮演游戏。迄今为止,《魔灵召唤》在全球的下载量超过 1.8 亿,收入超过 27 亿美元。《魔灵召唤》是目前全球最受欢迎的手游之一,这款游戏展现了一个奇幻世界,玩家必须收集并训练各种怪物,才能与其他玩家对战。 近十年过去了,这款游戏庞大的玩家社区依然很是活跃,而且仍在扩展,部分原因在于 Com2uS 不断发布新的内容和更新,使这款游戏历久弥新、十分刺激。Com2uS 《魔灵召唤:克罗尼柯战记》 US(WW) 和 KR by Com2uS 专门利用 Vulkan 在 Android 上进行渲染,可将性能提升高达 30%。 Vulkan 是一种现代化的跨平台 3D 图形 API,旨在最大限度减少设备图形硬件与您的游戏之间的抽象。与 OpenGL ES 相比,Vulkan 的 CPU 开销更低,并且 Vulkan 提供更广泛的功能。 Com2uS 为 《魔灵召唤:克罗尼柯战记》 开发了高级渲染功能,包括: 《魔灵召唤:克罗尼柯战记》 对 Android 《Ares: Rise of Guardians 》是一款移动设备转 PC 的科幻 MMORPG 游戏,由 Second Dive 开发,后者是一家位于韩国的游戏工作室,以其动作角色扮演系列开发方面的专业知识而闻名。该游戏由 Kakao Games 发布。 《阿瑞斯》以广袤的宇宙为背景,采用细节满满的未来主义背景。《阿瑞斯》充满了刺激的玩法和画面精美的角色,涉及身着战斗服的战斗人员。然而,由于这些细节丰富的图形,一些用户的设备在处理游戏内容时有些吃力。 Cat Daddy Games 是一家全资 2K 工作室,位于华盛顿州柯克兰,是 NBA 2K Mobile 的开发者。该团队希望提高游戏的整体质量和稳定性,具体方法是减少“应用无响应”错误 (ANR)。如果 Android 应用的界面线程处于阻塞状态的时间过长,就会发生 ANR。发生这种情况时,负责更新界面的应用主线程将无法绘制或处理用户输入事件,这会引起用户的不满。如果应用在前台运行,系统会显示一个对话框,允许用户强制退出应用。 减少 ANR 一直是 Cat Daddy 的首要任务。QA Devsisters 是一家全球性的移动游戏开发商和发布商,专门制作基于《跑跑姜饼人》IP 的休闲游戏。他们最受欢迎的游戏包括 《跑跑姜饼人:烤箱大逃亡》 (跑步街机)和 《跑跑王国》 (社交 RPG),这两款游戏都深受全球用户的喜爱,尤其是在韩国、台湾和美国。虽然《跑跑姜饼人:烤箱大逃亡》是一款休闲游戏,但五年积累的资源使 CDN 容量提高到了 2.5GB,这使得 CDN 费用的增加。Devsisters 需要找到一种可持续的模式来宣传他们的大文件游戏。 Devsisters 发现,大量的 NEW STATE Mobile 是 Krafton 的一款大逃杀游戏于 2021 年 11 月面向全球发布,在发布后的第一个月便获得了超过 4500 万次下载。KRAFTON, Inc. 是一个由多个独立的游戏开发工作室组成的联合公司,旨在为全球游戏玩家打造富有吸引力的创新娱乐体验。该公司包括 PUBG Studio、Bluehole Studio、Striking Distance Studio、RisingWings、Dreamotion 和 Unknown Spokko 住在波兰,是一群雄心勃勃的创作者,他们致力于打造要求极为严苛的 IP。Spokko 是 CD PROJEKT 家族的成员,但是一家独立公司,已将 《巫师:怪物杀手》 的精彩世界转移到智能手机上。 《巫师:怪物杀手》是一款使用增强现实技术的基于位置的角色扮演游戏。这是一款计算密集型游戏,会给许多设备带来挑战。发布之初,Spokko 希望确保其游戏可以覆盖尽可能多的用户,同时为所有人提供高品质的体验。 Cat Daddy Games 是一家全资 2K 工作室,总部位于华盛顿州柯克兰。NBA 2K Mobile、NBA SuperCard 和 WWE SuperCard 系列背后的团队正在寻找一个解决方案来为用户提高游戏的整体质量,具体方法是在支持这些游戏的设备上提供更优质的素材资源。 他们实现了 Play Asset Delivery,以简单而更灵活的方式针对每位用户的设备配置生成并提供经过优化的 APK,并使用纹理压缩格式定位功能针对特定设备提供更好的美术资源并减少资源下载。 首先,Cat Unreal Engine 是由 Epic Games 开发的游戏引擎,可为各行各业的创作者提供自由和控制权,让他们提供先进的娱乐、富有吸引力的可视化内容和沉浸式虚拟世界。一些主要的 Android 游戏都是使用 Unreal Engine 构建的。 图 1. 在 Pixel 4 上运行的 Unreal Engine Suntemple 示例的屏幕截图 Epic 和其他游戏开发者使用 Android Studio 调试 C++、Kotlin 或 Java 编程语言,但许多游戏开发者都有以 Electronic Arts (EA) 是一家总部位于美国加利福尼亚州的游戏公司。它制作了各种不同类型的游戏,例如体育、动作、赛车和模拟游戏。EA 的开发工作室 Firemonkeys 因开发 真实赛车 3 、 模拟人生自由玩 和 Need For Speed: No Limits 而闻名于世。Firemonkeys 使用自定义游戏引擎来开发游戏,现在他们的所有 Android 游戏都在其开发工作流中使用 Android Game Development Extension (AGDE) 游戏开发商 CD Projekt RED (CDPR) 位于波兰华沙,他们重新构思了自己的迷你游戏《巫师 3》、 《巫师之昆特牌》 ,并于 2020 年 3 月在 Google Play 上以独立的免费畅玩形式发布。由于初始文件较大,且定期更新需要额外的设备存储空间,用户通常必须重新安装完整版游戏,才能获得更新的版本。这是游戏社区中最突出的挫败点。为了帮助进行差分修补,CDPR 通过实现 Play Asset Delivery 取得了巨大的成功。 CDPR 是实现 Play Asset 20 多年来, Gameloft 为数字平台打造了富有创意的游戏体验,从移动游戏到跨平台 PC 和主机游戏,不一而足。除了自有的知名游戏系列外,Gameloft 还为乐高、环球和长宝等热门品牌开发游戏。他们的游戏团队在全球拥有 3,600 名员工,每月可在 100 多个国家/地区覆盖 5500 万唯一身份玩家。 竞速街机游戏 Asphalt 9: Legends 于 2018 年首次发布,他们需要找到一种平衡性能、保真度和电池的方式。为此,Gameloft 怀着对游戏的热情以及将游戏带给世界各地玩家的渴望, Gameloft 于 2000 年成立。他们是开发移动游戏的先驱,现在旗下有超过 190 款游戏。Gameloft 的许多移动游戏是图形密集型游戏,下载大小较大。这使得他们成为 Google Play Asset Delivery (PAD) 早期开发阶段一个极具吸引力的合作伙伴。PAD 是一套基于我们的 app bundle 基础架构构建的游戏服务分发功能。PAD 会在适当的时间免费向适当的设备提供免费、动态的适当游戏素材资源。这引起了 RV AppStudios 是一家总部位于美国的游戏开发商,该公司旗下的休闲游戏、教育儿童应用和实用类应用到目前为止已有超过 2 亿的下载量。该团队在其应用 Puzzle Kids - Animals Shapes and Jigsaw Puzzles 中引入了 Google Play Asset Delivery,属于早期测试用户。他们希望优化应用的大小,节省资金,并在需要下载新的资源包时消除任何干扰,从而提升用户体验。 当用户安装 Puzzle Kids Pixonic 是一个总部位于莫斯科的视频游戏开发团队,其以抓住每一个机会升级自己的移动应用并覆盖更广泛的玩家群体为荣。该公司最著名的游戏之一是 《War Robots》 ,这是一款 12 人的玩家对战 (PVP) 游戏,玩家可以在即时战场上操作定制的机器人进行决斗。 《War Robots》于 2014 年发布,最初是专为 Android 的早期设备设计的,通过触控板操控游戏角色,用不到鼠标。Pixonic Gameloft 一直致力于成为首批在最新便携式硬件上发布游戏的开发商之一,以便随时随地为玩家提供激动人心的体验。因此,Gameloft 知道 ChromeOS 是适合其移动赛车系列最新游戏《狂野飙车 8:极速凌云》的平台。 Gameloft 非常了解如何针对不同的设备开发游戏,但将 Asphalt 体验转换为 Chromebook 特有的触摸屏/键盘混合控制(可随时切换)似乎具有挑战性。然而,结果证明这个过程没有想象的那么困难,值得一试。 利用 ChromebookMir 2 通过使用 Frame Pacing 库来提升渲染性能
Kuro Games 使用 Android Studio 功耗性能分析器和 ODPM 为 Wuthering Waves 降低了 9.68% 的功耗
适用于 Android 的 Godot Engine Vulkan 优化
在 Unreal Engine 中使用 Android 动态性能框架 (ADPF) 入门
NCSoft Lineage W 使用 ADPF 提高了持续性能并防止温控降频
MediaTek 提升了 Android SoC 的动态性能
《使命召唤:战争地带手游》使用 Vulkan 提升图形效果
Com2uS - Google Play 游戏电脑版
Com2uS 使用 Vulkan 提升图形效果
Kakao Games 通过 Android 自适应功能将 FPS 稳定性提升至 96%
2K 利用 Android Game Development Kit 将 ANR 发生率降低了 35%
《跑跑姜饼人:烤箱大逃亡》通过 Play Asset Delivery 节省了超过 20 万美元的 CDN 费用
新 STATE Mobile 利用 Android GPU 检查器将 GPU 使用量降低了 22%
《The Witcher: Monster Slayer》借助 Android Performance Tuner 扩大覆盖面
2K 借助 Play Asset Delivery 提供高清画质
“AGDE 简直太棒了!”;使用 Unreal Engine 进行 Android 开发
Firemonkeys 借助 AGDE 缩短了开发和调试时间
CD Projekt RED 借助 Play Asset Delivery 将游戏更新大小缩减了 90% 并将更新率提高了 10%
借助 Game Mode API,Gameloft 将设备功耗降低了 70%,从而使游戏时长延长了 35%
Gameloft 借助 Google Play Asset Delivery 将新用户数增加了 10%
RV AppStudios 借助 Google Play Asset Delivery 提高了用户留存率
Pixonic 针对大屏设备进行优化后,在 ChromeOS 上的互动度提高了 25%
Gameloft 针对 ChromeOS 进行优化后,收入迅速提升了 9 倍
Пока рекомендаций нет.
Попытайтесь войти в свой аккаунт Google.