-
- Неэффективное использование ресурсов: Неправильное управление памятью, чрезмерное использование CPU или неправильное использование сетевых запросов может замедлить приложение.
- Проблемы с пользовательским интерфейсом: Сложные или плохо оптимизированные анимации и интерфейс могут вызывать задержки в отклике.
- Выполнение тяжелых операций в главном потоке: Выполнение длительных операций, таких как доступ к базе данных или сетевые запросы, в главном потоке UI может привести к "зависанию" приложения.
- Утечки памяти: Утечки памяти происходят, когда объекты не освобождаются после использования, что со временем может привести к истощению доступной памяти и замедлению приложения.
-
Contextв Android — это интерфейс, который предоставляет доступ к глобальной информации о приложении. Он используется для получения доступа к ресурсам, файловым системам, вызова активностей и служб. Существует три типа контекста:ApplicationContext,ActivityContext,BaseContext.ApplicationContextсвязан с жизненным циклом приложенияActivityContextсвязан с жизненным циклом активности.BaseContextв Android является базовым классом контекста (Context). Он используется как родительский класс дляActivityContextиApplicationContext, предоставляя основные функции контекста, которые могут быть расширены или использованы в этих специализированных контекстах.BaseContextобеспечивает доступ к ресурсам и системным службам, таким как запуск активностей, взаимодействие с различными сервисами Android и управление ресурсами приложения. В контексте Android разработки, когда говорят оBaseContext, чаще всего имеют в виду фундаментальную функциональность контекста, на которой основаны все другие типы контекстов.
Context необходим для:
- Доступа к базовым функциям приложения, таким как доступ к ресурсам, базам данных и настройкам.
- Запуска других компонентов, таких как активности и службы.
- Взаимодействия с другими приложениями.
-
Основные компоненты Android приложения включают:
- Activity - компонент, который представляет один экран с пользовательским интерфейсом.
- Service - компонент для выполнения долгосрочных операций в фоновом режиме.
- Broadcast Receiver - компонент, который позволяет приложению получать и обрабатывать сообщения от других приложений или от системы. Эти сообщения могут касаться различных событий, таких как изменение состояния сети, низкий уровень заряда батареи или загрузка системы.
- Content Provider - это компонент, который предоставляет доступ к данным приложения другим приложениям и компонентам. Content Providers полезны для чтения и записи данных, которые должны быть доступны другим приложениям, например, контактов, календарных событий или фотографий.
-
AndroidManifest.xml— это файл в Android приложении, который содержит важную информацию о приложении для Android системы. Он объявляет конфигурацию приложения, включая его компоненты (активности, службы, получатели широковещательных сообщений, поставщики контента), требуемые разрешения, минимальный уровень API Android, используемый приложением, и другие настройки.AndroidManifest.xmlчитается системой при установке приложения, и на основе этой информации система знает, как взаимодействовать с приложением. -
Broadcast Receiver - обычно необходимо объявлять, но существует возможность динамической регистрации (в коде, а не в манифесте) для некоторых случаев использования.
-
Класс
Applicationв Android представляет собой базовый класс приложения, который содержит глобальное состояние приложения. Он выполняется до того, как любой другой код приложения будет запущен, и именно здесь можно инициализировать глобальные ресурсы. КлассApplicationможно использовать для выполнения действий и настройки компонентов, которые должны быть доступны во всем приложении, например, инициализации библиотек, настройки управления сессиями или предоставления контекста для использования в других компонентах приложения. -
Запуск в контексте системы:-
Нажатие на иконку приложения: Когда пользователь нажимает на иконку, запускается интент запуска (launch intent), который определяет, какое Activity должно быть запущено. Этот интент обрабатывается системным диспетчером задач (ActivityManager).
-
ActivityManager: ActivityManager определяет, запущен ли уже процесс для этого приложения. Если процесс не запущен, система начинает процедуру его создания.
-
Zygote: Android использует механизм под названием Zygote для запуска процессов приложений. Zygote — это предварительно загруженный демон системы, который содержит предзагруженную виртуальную машину Dalvik или ART (в зависимости от версии Android). Когда требуется создать новый процесс приложения, Zygote порождает новый процесс путем вызова fork(). Это позволяет быстро и эффективно запускать приложения, поскольку общий код и ресурсы Android уже загружены в память.
Запуск в контексте приложения:
-
Инициализация приложения: После создания процесса для приложения система загружает Application класс приложения (если он указан) и вызывает его метод onCreate(). Это самый первый код, который исполняется в рамках процесса приложения.
-
Запуск Activity: После инициализации приложения система создает экземпляр основного Activity, указанного в интенте запуска, вызывая его метод onCreate(). Здесь приложение обычно загружает свой пользовательский интерфейс и выполняет начальную настройку.
-
Отображение Activity: После того как Activity было создано и инициализировано, система делает его видимым для пользователя, вызывая методы onStart() и onResume(). В этот момент пользователь видит UI приложения и может с ним взаимодействовать.
-
-
В Android обновление пользовательского интерфейса (UI) не из основного потока (также известного как UI поток) запрещено из-за модели однопоточности, которую Android использует для управления пользовательским интерфейсом.
-
Выполнение тяжелой или блокирующей работы в классе Application может привести к замедлению запуска приложения и ухудшению впечатлений пользователя, поскольку это может заблокировать главный поток UI. Класс Application предназначен для инициализации глобального состояния приложения, а не для выполнения фоновой работы.
-
Иконка приложения добавляется на рабочий стол (launcher screen) когда в манифесте приложения активити определено с интент-фильтром ACTION.MAIN и категорией LAUNCHER. При нажатии на иконку запускается активити, указанное как точка входа приложения.
-
Если установить несколько активити с интент-фильтром для лаунчера, пользователю будет предложен выбор активити для запуска при нажатии на иконку приложения. Это может быть использовано для предоставления различных точек входа в приложение
-
Если бы перед вами стояла задача залогировать самую раннюю точку старта приложения, в каком месте бы вы разместили код?
Самая ранняя точка, где можно разместить код логирования - это метод onCreate() класса Application. Этот метод вызывается при старте приложения до любого другого компонента (Activity, Service и т.д.).
Но и также это может быть broadcast receiver. Broadcast Receiver регистрируется для BOOT_COMPLETED и срабатывает немедленно после его получения. -
Обновлять UI-компоненты (view) напрямую из не-UI потока нельзя из-за ограничений Android на доступ к UI-элементам только из главного потока. Для обновления UI из других потоков используются механизмы синхронизации, такие как
runOnUiThread()или Handler. -
В Android приложениях не используется метод
main()в традиционном смысле, как в Java-приложениях. Вместо этого, точкой входа служит компонент Activity (или другие компоненты, такие как Service, BroadcastReceiver), который запускается системой Android, когда необходимо выполнить определенное действие (например, открыть приложение). Система Android использует манифест приложения для определения компонента, который должен быть запущен.
Если объявлен Application, то вызывается он. -
Метод
onCreate()в классе Application вызывается при создании процесса приложения и служит для инициализации ресурсов, необходимых на протяжении всего существования приложения. ОтсутствиеonDestroy()объясняется тем, что процесс приложения уничтожается системой без каких-либо предупреждений, когда системе необходимо освободить ресурсы. Поэтому логика, требующая гарантированного выполнения перед завершением работы приложения, должна располагаться в других компонентах (например, в Activity или Service).
-
При восстановлении системой фрагментов (например, при пересоздании активности после изменения конфигурации) используется конструктор без параметров. Если вы создадите фрагмент с конструктором с параметрами и не сохраните эти параметры в onSaveInstanceState, вы можете потерять эти данные при пересоздании фрагмента, что приведет к ошибкам или непредвиденному поведению.
-
Activity - это компонент приложения, предоставляющий экран с пользовательским интерфейсом. Жизненный цикл Activity включает методы: onCreate(), onStart(), onResume(), onPause(), onStop(), onRestart(), onDestroy().
- onCreate() вызывается при первом создании активности. Здесь происходит инициализация.
- onStart() вызывается, когда активность становится видимой пользователю.
- onResume() вызывается, когда активность вступает в фокус и готова к взаимодействию с пользователем.
- onPause() вызывается при переходе активности в состояние "пауза", когда она все еще видима, но уже не в фокусе.
- onStop() вызывается, когда активность больше не видна пользователю.
- onDestroy() вызывается перед тем, как активность будет уничтожена.
- onRestart() вызывается после того, как активность была остановлена и снова была запущена пользователем.
-
Основное различие между onCreate() и onStart() заключается в их роли в жизненном цикле Activity: onCreate() служит для инициализации Activity и вызывается один раз, когда Activity создается, в то время как onStart() делает Activity видимым для пользователя и может вызываться многократно каждый раз, когда Activity переходит в видимое состояние.
-
Это может произойти в крайне редких случаях, например, если система уничтожает процесс приложения для освобождения ресурсов в условиях нехватки памяти. В обычной ситуации onPause() и onStop() всегда вызываются перед onDestroy().
-
setContentView() устанавливает макет пользовательского интерфейса для активности и должен быть вызван в onCreate(), чтобы до начала взаимодействия с пользователем активность имела загруженный и готовый интерфейс.
-
- Длительные операции, такие как сетевые запросы или обращение к базе данных, так как это может привести к "зависанию" приложения. Такие операции следует выполнять асинхронно.
- Изменение конфигурации, не связанной с инициализацией UI, которая может быть выполнена в других методах жизненного цикла.
-
onSaveInstanceState()- Этот метод используется для сохранения данных перед паузойActivity.onRestoreInstanceState()- Этот метод используется для восстановления сохраненного состоянияActivity, когдаActivityпересоздается после уничтожения. Таким образом,onRestoreInstanceState()получает пакет, который содержит информацию о состоянии экземпляра.
-
- standard: Запускает активити в новом экземпляре каждый раз.
- singleTop: Если экземпляр активити уже находится на вершине стека, он не создается заново, и вместо этого получает интент.
- singleTask: Создает новый задачный стек и запускает активити в новом экземпляре в этом стеке, но если активити уже существует в любом стеке, система очищает стек до этого активити и отправляет интент.
- singleInstance: Активити запускается в новом задачном стеке, но с гарантией того, что никакие другие активити не будут запущены в этом стеке.
-
Fragment– это компонент приложения, который имеет свой жизненный цикл, получает события ввода и может быть добавлен в активность. Жизненный цикл фрагмента включает такие методы, как onAttach(), onCreate(), onCreateView(), onActivityCreated(), onStart(), onResume(), onPause(), onStop(), onDestroyView(), onDestroy(), onDetach():- onAttach() - вызывается, когда фрагмент связывается с активностью.
- onCreate() - система вызывает этот метод, когда создает фрагмент. Создайте здесь компоненты, которые необходимы вне видимости пользователя.
- onCreateView() - вызывается для создания макета фрагмента. В этом методе вы должны создать и вернуть макет фрагмента.
- onViewCreated() - Вызывается сразу после onCreateView(), когда представление фрагмента уже создано. Это хорошее место для инициализации представлений.
- onActivityCreated() - вызывается, когда активность, к которой прикреплен фрагмент, завершила свой метод onCreate().
- onStart() - вызывается, когда фрагмент становится видимым.
- onResume() - вызывается, когда фрагмент получает фокус и может взаимодействовать с пользователем.
- onPause() - вызывается, когда пользователь теряет фокус на фрагменте, и можно сохранить изменения или обновления.
- onStop() - вызывается, когда фрагмент больше не видим.
- onDestroyView() - вызывается при удалении макета фрагмента.
- onDestroy() - вызывается при уничтожении фрагмента.
- onDetach() - вызывается, когда фрагмент отсоединяется от активности.
-
- Транзакции фрагментов используются для добавления, удаления, замены фрагментов в активити во время выполнения. Это позволяет динамически изменять состав интерфейса.
- Операции с фрагментами обрабатываются атомарно как единая транзакция.
-
launchMode определяет, как активность будет вставлена в стек задач. singleTask – это режим запуска, при котором в стеке задач может быть только один экземпляр активности. Если активность уже находится в стеке, система очищает все активности, находящиеся над ней, и передает интент этой активности через onNewIntent().
-
Activity действует как контейнер для пользовательского интерфейса и управляет взаимодействием пользователя с экраном. Fragment, с другой стороны, представляет собой повторно используемую часть пользовательского интерфейса с собственным жизненным циклом, которая может быть встроена в активность. Фрагменты добавляют гибкость в проектирование интерфейса, позволяя активности включать несколько фрагментов на одном экране и переиспользовать фрагмент в разных активностях.
-
- Когда у вас есть некоторые компоненты пользовательского интерфейса, которые должны использоваться в различных
Activity - Когда несколько представлений могут быть отображены бок о бок, как например
ViewPager
- Когда у вас есть некоторые компоненты пользовательского интерфейса, которые должны использоваться в различных
-
FragmentPagerAdapter: КаждыйFragment, посещенный пользователем, будет храниться в памяти, но представление будет уничтожено. Когда страница снова посещается, то создается представление, а не экземпляр фрагмента.FragmentStatePagerAdapter: Здесь экземпляр фрагмента будет уничтожен, когда он не виден пользователю, за исключением сохраненного состояния фрагмента.
-
При добавлении фрагмента, он размещается поверх предыдущего, не удаляя его, в то время как замена удаляет текущий фрагмент и добавляет новый. Использование addToBackStack() позволяет возвращаться к предыдущему фрагменту с помощью кнопки "Назад".
-
- Через ViewModel
- Через Activity
-
По умолчанию,
Fragmentsуничтожаются и пересоздаются вместе с их родительскимиActivitiesпри изменении конфигурации. ВызовsetRetainInstance(true)позволяет нам обойти этот цикл уничтожения и пересоздания, сигнализируя системе о сохранении текущего экземпляра фрагмента, когдаActivityпересоздается. -
При вызове
addToBackStack(), транзакция замены сохраняется в стеке возврата, так что пользователь может отменить транзакцию и вернуть предыдущий фрагмент, нажав кнопку Назад.
-
View объекты являются основными строительными блоками элементов пользовательского интерфейса (UI) в
Android. View это простая прямоугольная коробка, которая реагирует на действия пользователя. Примеры включаютEditText,Button,CheckBoxи т. д. View относится к классуandroid.view.View, который является базовым классом всех классов UI.
- Measure (Измерение): На этом этапе система определяет размеры View. Родительский элемент спрашивает каждого из своих дочерних элементов, сколько места они нуждаются для отображения. Это делается через вызов метода measure(int, int). Дочерние элементы должны затем самостоятельно вычислить и указать свои размеры, вызывая метод setMeasuredDimension(int, int). Этот процесс рекурсивно повторяется для всех элементов иерархии View.
- Layout (Размещение): После того как были измерены размеры всех View, начинается этап размещения. На этом этапе определяется, где именно в родительском элементе будет находиться каждый дочерний элемент. Это делается путем вызова метода layout(int, int, int, int), который устанавливает фактические положение и размер каждого View. Координаты и размеры задаются относительно родительского элемента.
- Draw (Отрисовка): На последнем этапе система отрисовывает View на экране. Это включает в себя отрисовку фона, содержимого (текст, изображения и т.д.) и любых анимаций или декораций. Отрисовка происходит в методе draw(Canvas), который вызывает такие методы, как onDraw(Canvas), dispatchDraw(Canvas) для дочерних элементов и onDrawForeground(Canvas) для отрисовки элементов переднего плана (например, прокрутки или фокуса).
-
onAttachedToWindow(): Этот метод вызывается, когда View было прикреплено к окну. Это первый шаг, когда View становится видимым в приложении. Здесь можно инициализировать анимации или начать мониторить изменения в системе. Это также сигнализирует, что View теперь может взаимодействовать с пользователем.
-
measure(): Это внутренний метод системы Android, который запускает процесс измерения View путём вызова onMeasure(). Этот метод не предназначен для переопределения, но он важен, так как инициирует определение размера View.
-
onMeasure(int, int): В onMeasure(), View определяет, какого размера оно должно быть, исходя из предложений (specifications) родительского элемента. View должно вызвать setMeasuredDimension(int width, int height) для сохранения измеренных размеров. Это переопределяемый метод, который вы можете использовать, чтобы управлять размером вашего View.
-
layout(): Это другой внутренний метод системы, который вызывается после завершения процесса измерения. Он отвечает за расположение View в родительском контейнере. Этот метод также не предназначен для переопределения.
-
onLayout(boolean, int, int, int, int): После метода layout(), onLayout() вызывается для того, чтобы View расположило себя и все свои дочерние элементы. В случае с ViewGroup, здесь определяется местоположение дочерних View. Это переопределяемый метод, где вы устанавливаете, где должны находиться дочерние элементы внутри ViewGroup.
-
dispatchDraw(Canvas): dispatchDraw используется в ViewGroup для рисования дочерних View. Этот метод вызывается системой для рисования содержимого, и обычно его не нужно переопределять, но вы можете это сделать, чтобы управлять тем, как ваши дочерние View рисуются.
-
draw(Canvas): Это внутренний метод, который управляет всем процессом рисования, включая вызов onDraw(), рисование фона, дочерних представлений, скроллирования и т. д. Этот метод обычно не переопределяется, так как он обрабатывает несколько задач рисования и делегирует основную работу onDraw().
-
onDraw(Canvas): onDraw() — это где вы определяете, как View должно отображать свое содержимое. Это может включать рисование форм, текста, изображений или других графических элементов. Этот метод переопределяется, когда вы создаете пользовательский View и хотите контролировать его визуальное представление.
-
invalidate(): Вызывается, когда view должно быть перерисовано, но его размер и позиция не изменяются.requestLayout(): Вызывается, когда view должно быть измерено и размещено заново, что может привести к изменению размеров и позиции как этого view, так и его потомков.
-
- View.GONE - этот параметр делает представление полностью невидимым и не занимает место в макете.
- View.INVISIBLE - представление остается невидимым, но все еще занимает место в макете.
-
Да, можно создать пользовательский View в Android. Это делается путем наследования от класса View или одного из его подклассов и переопределения методов, таких как
onDraw(), для рисования контента вида илиonMeasure()для определения размера вида. -
- View - объекты View являются основными строительными блоками элементов пользовательского интерфейса (UI) в
Android. View это простая прямоугольная коробка, которая реагирует на действия пользователя. Примеры включаютEditText,Button,CheckBoxи т. д. View относится к классуandroid.view.View, который является базовым классом всех классов UI. - ViewGroup - ViewGroup это невидимый контейнер. Он содержит Views и ViewGroups. Например,
LinearLayoutэто ViewGroup, который содержитButton(View), и другие компоновки также. ViewGroup является базовым классом для компоновок.
- View - объекты View являются основными строительными блоками элементов пользовательского интерфейса (UI) в
-
Canvas — это одна из основных функций встроенного в Android фреймворка графического интерфейса, которая позволяет создавать разнообразные пользовательские интерфейсы и реализовывать сложную графику. С помощью этого инструмента разработчики могут реализовывать различные возможности, такие как рисование, анимация и обработка событий.
-
SurfaceView — это подкласс View, который предоставляет отдельный слой, на котором можно рисовать, не блокируя основной поток пользовательского интерфейса. Это полезно для рендеринга анимаций или видео, где требуется высокая производительность и меньшее взаимодействие с основным потоком UI.
-
- Relative Layout позволяет размещать виджеты относительно друг друга или относительно родительского контейнера.
- Linear Layout размещает виджеты в линейной последовательности, горизонтально или вертикально.
-
Constraint Layout — это гибкий и мощный макет в Android, который позволяет создавать сложные пользовательские интерфейсы без вложенных макетов. Он предоставляет широкие возможности для определения ограничений для позиционирования и размера виджетов, что облегчает создание адаптивных интерфейсов.
-
Дерево из View — это иерархическая структура, которая представляет все виджеты (views) и макеты (layouts), составляющие пользовательский интерфейс в Android приложении. Оптимизировать глубину дерева View можно путем уменьшения количества вложенных макетов, использования ConstraintLayout для упрощения иерархии и избегания лишних макетов, которые не вносят вклад в пользовательский интерфейс. ViewTreeObserver может использоваться для прослушивания различных событий в дереве View, таких, как момент перед отрисовкой, что может быть полезно для дополнительных оптимизаций.
-
-
ListView — это виджет для отображения списка данных в вертикальном порядке, который был частью Android с его первых версий. Он поддерживает базовую прокрутку и может отображать список, который подгружается в адаптер. Однако он имеет ограниченные возможности по настройке и не поддерживает разные типы элементов списка или сложные анимации.
-
RecyclerView — это более продвинутый и гибкий компонент для отображения списков данных, введенный в Android Lollipop (API уровня 21). Он поддерживает как вертикальную, так и горизонтальную прокрутку, разные типы элементов, сложные анимации, а также имеет более эффективное переиспользование элементов списка через механизм ViewHolder. RecyclerView также позволяет легко реализовать разные виды лэйаутов, такие как список, сетка и стаггеред грид.
-
-
RecyclerView работает на основе адаптера, который управляет данными списка и связывает эти данные с видами, отображаемыми в RecyclerView. Ключевым компонентом является паттерн ViewHolder, который хранит ссылки на все подвиды каждого элемента списка для быстрого доступа без необходимости повторного поиска. При прокрутке списка RecyclerView переиспользует виды, которые вышли за пределы экрана, применяя к ним новые данные, что значительно повышает производительность и эффективность использования памяти.
-
- Использование метода setHasFixedSize(true), если размер RecyclerView не изменяется, что позволяет оптимизировать производительность.
- Эффективное использование ViewHolder для минимизации вызовов findViewById внутри адаптера.
- Избегание сложных операций в методе onBindViewHolder адаптера, таких как загрузка изображений без кэширования. Вместо этого рекомендуется использовать библиотеки для асинхронной загрузки изображений, например, Glide.
- Оптимизация макетов элементов списка, избегая лишней вложенности.
-
- Убедитесь, что внешний RecyclerView и вложенные RecyclerView используют setHasFixedSize(true), если их размеры не изменяются.
- Используйте пулинг вьюхолдеров с помощью setRecycledViewPool(RecyclerView.RecycledViewPool) для переиспользования элементов в разных RecyclerView.
- Минимизируйте количество вызовов notifyDataSetChanged() и используйте более конкретные методы уведомления об изменениях, такие как notifyItemChanged(int), для улучшения производительности.
-
SnapHelper — это класс помощник, предназначенный для вспомогательной привязки (snapping) элементов RecyclerView к определенной точке на экране, обычно в центре или краях экрана, когда прокрутка останавливается. Это удобно, например, для создания галерей или каруселей, где требуется, чтобы элементы выравнивались относительно определенных точек.
-
DiffUtil — это утилита, предоставляемая Android SDK, которая помогает вычислить разницу между двумя списками и выдать набор операций обновления, необходимых для преобразования одного списка в другой. Это может использоваться в адаптере RecyclerView для минимизации количества обновлений и повышения производительности, особенно когда изменения в данных минимальны. DiffUtil вычисляет минимальное количество изменений и автоматически обновляет список с анимациями, делая пользовательский интерфейс более плавным и отзывчивым.
-
Dialog — это небольшое окно, которое появляется перед пользователем для выполнения действия или для отображения информации, не перекрывая полностью основной контент. Диалоги могут быть использованы для сбора пользовательского ввода через формы, отображения сообщений, выбора дат и других интерактивных элементов.
-
Toast — это маленькое всплывающее сообщение, которое отображается на короткое время и автоматически исчезает после истечения времени отображения. Toast обычно используется для отображения неинтерактивных сообщений, информирующих пользователя о каком-либо процессе (например, "Сообщение отправлено").
-
Основная разница между Dialog и DialogFragment заключается в управлении жизненным циклом и встраивании в архитектуру приложения:
- Dialog — это базовый класс для диалогов, который может быть использован напрямую, но его управление в контексте жизненного цикла активности может быть сложным.
- DialogFragment — это фрагмент, который предоставляет API для отображения диалога. Использование DialogFragment рекомендуется, так как он лучше интегрируется в жизненный цикл активности или фрагмента, позволяя управлять диалогом так же, как и другими компонентами Android.
-
Intent — это абстрактное описание операции, которое должно быть выполнено. В Android Intent используется для запуска активностей, сервисов и для передачи сообщений между компонентами приложения или разными приложениями.
-
Неявный Intent не указывает прямо на компонент, который должен обработать действие. Вместо этого он определяет общее действие, которое может быть выполнено любым приложением или компонентом, способным его обработать. Примером может служить намерение открыть веб-страницу, где не указан конкретный браузер, но задано действие ACTION_VIEW.
-
Явный Intent указывает непосредственно на компонент, который должен обработать действие, включая имя пакета или полное имя класса компонента. Явные Intent обычно используются для запуска компонентов внутри того же приложения.
-
BroadcastReceiver — это компонент приложения, который позволяет реагировать на широковещательные сообщения от других приложений или от самой системы. Эти сообщения могут касаться различных событий, таких как изменение заряда батареи, получение SMS или изменение сетевого состояния.
-
Липкий Intent (Sticky Intent) — это широковещательное сообщение, которое после отправки "застревает" в системе, позволяя новым подписчикам на BroadcastReceiver получить данные события даже после его завершения. Примером использования может быть запрос текущего состояния батареи. Следовательно, вы можете использовать это для определения состояния батареи без обязательной регистрации всех будущих изменений состояния батареи.
-
Broadcasts и intents позволяют компонентам приложения общаться между собой без необходимости напрямую связывать их код. Intents могут быть использованы для явного запуска компонентов внутри приложения или для неявного запроса действий от других приложений. Broadcasts позволяют отправлять широковещательные сообщения системе или приложениям, на которые подписаны BroadcastReceivers, реагирующие на определенные события или интенты.
-
PendingIntent — это токен, который вы передаете внешнему приложению (например, уведомлению, виджету), который позволяет этому приложению использовать разрешение вашего приложения для выполнения предопределенной операции. В основном, PendingIntent используется для уведомлений, чтобы открыть активность или выполнить сервис при нажатии на уведомление.
-
Service – это компонент приложения, который может выполнять длительные операции в фоновом режиме и не предоставляет пользовательского интерфейса. Другими словами, это способ выполнить некоторые действия в фоне, например, проигрывание музыки, загрузку файлов и т. д., без взаимодействия с пользовательским интерфейсом. Сервисы могут быть как связанными (bound), так и несвязанными. Связанный сервис предлагает клиент-серверный интерфейс, который позволяет компонентам (например, активности) взаимодействовать с сервисом, отправлять запросы, получать результаты через IPC (Межпроцессное взаимодействие). Несвязанный сервис обычно выполняется на заднем плане и не связан с каким-либо пользовательским интерфейсом или компонентом, который его запустил.
-
Сервис переднего плана (Foreground Service) – это сервис, который выполняется на переднем плане и обязательно показывает уведомление в строке состояния. Это уведомление информирует пользователя о том, что приложение выполняет некоторую задачу, которая требует внимания пользователя. Сервисы переднего плана обычно используются для задач, которые непосредственно влияют на работу пользователя с устройством, например, для проигрывания аудио или для выполнения активной задачи, такой как навигация. Использование сервиса переднего плана помогает обеспечить, что система не остановит ваше приложение, пока выполняется важная задача.
-
JobScheduler – это системный сервис, доступный начиная с Android 5.0 (API уровень 21), который позволяет разработчикам планировать различные виды задач (работы) для выполнения в определенных условиях. С помощью JobScheduler можно управлять выполнением задач в зависимости от таких условий, как состояние сети, заряд батареи и другие. Это позволяет приложениям выполнять фоновые задачи более эффективно, экономя заряд батареи и ресурсы системы. Работы, запланированные с помощью JobScheduler, могут выполняться даже после перезагрузки устройства.
-
- Интенты (Intents): Интенты позволяют приложениям запрашивать функциональность от других приложений. Например, приложение может использовать интент для запуска камеры или выбора контакта из списка контактов.
- Сервисы (Services): Приложение может использовать сервисы другого приложения для выполнения фоновых задач без взаимодействия с пользовательским интерфейсом.
- Content Providers: Позволяют делиться данными между приложениями. Например, приложение может обращаться к базе данных контактов через ContentProvider.
- Межпроцессное взаимодействие (IPC): С использованием AIDL (Android Interface Definition Language) приложения могут обмениваться данными и объектами.
-
Да, приложение Android может работать в нескольких процессах. Это можно настроить в манифесте приложения, указав атрибут android:process в теге компонента (
<activity>,<service>,<receiver>,<provider>). Каждый компонент может быть настроен на запуск в отдельном процессе, что позволяет приложению выполнять различные задачи в разных процессах одновременно. -
AIDL (Android Interface Definition Language) используется для создания интерфейсов, которые позволяют клиентам взаимодействовать с сервисом через межпроцессное взаимодействие (IPC). Для создания ограниченного сервиса через AIDL необходимо выполнить следующие шаги:
- Определение интерфейса AIDL: Создайте файл AIDL с описанием методов, которые должны быть доступны для клиентов.
- Реализация интерфейса: Создайте класс, который реализует интерфейс, определенный в AIDL. Этот класс будет обрабатывать вызовы от клиентов.
- Регистрация сервиса в манифесте: Укажите сервис в AndroidManifest.xml, добавив соответствующий тег .
- Привязка к сервису: Клиенты могут привязаться к сервису, используя bindService(), чтобы начать взаимодействие с ним.
-
- Сервисы (Services): Для выполнения длительных задач на фоне.
- JobScheduler: Для планирования задач, которые должны выполняться при определенных условиях.
- WorkManager: Для гарантированного выполнения фоновых задач и работы с ограничениями, накладываемыми системой на фоновую работу.
- IntentService: Для обработки асинхронных запросов через интенты на фоне.
-
ContentProvider – это компонент приложения, который позволяет делиться данными между разными приложениями. Он предоставляет структурированный интерфейс к данным, хранящимся в файловой системе, базе данных SQLite, вебе или любом другом постоянном хранилище данных, которым управляет приложение. ContentProvider чаще всего используется для доступа к данным в разных приложениях, например, для доступа к контактам, календарю и другим личным данным пользователя.
-
-
Future и ExecutorService: Создайте пул потоков с помощью ExecutorService и запустите задачи в виде объектов Callable или Runnable. Используйте Future для отслеживания состояния выполнения каждой задачи. После завершения всех задач можно выполнить обратный вызов.
-
CountDownLatch: Этот инструмент позволяет одному или нескольким потокам ожидать завершения определенного количества операций в других потоках. Инициализируйте CountDownLatch с числом параллельных задач и уменьшайте счетчик при завершении каждой задачи. Когда счетчик достигнет нуля, можно выполнить обратный вызов.
-
RxJava: Библиотека для реактивного программирования, которая позволяет эффективно управлять асинхронными задачами и обработкой событий. С помощью операторов zip или merge можно объединить результаты нескольких асинхронных операций и получить уведомление при их завершении.
-
Kotlin Coroutines: В Kotlin для параллельного выполнения задач и получения результатов можно использовать корутины с применением функций async и await внутри CoroutineScope. Это позволяет писать асинхронный код, который выглядит как синхронный, и легко получать результаты выполнения задач.
-
-
ANR (Application Not Responding) – это ошибка, которая происходит, когда приложение не отвечает на ввод пользователя в течение 5 секунд. Чаще всего ANR возникает, если приложение выполняет длительные операции в главном потоке (UI thread).
Предотвращение ANR:- Использование фоновых потоков: Выполняйте длительные операции (например, сетевые запросы, обращение к базе данных) в фоновых потоках, не блокируя главный поток.
- AsyncTask (до API уровня 30): AsyncTask позволял выполнять асинхронные операции на фоне, но был объявлен устаревшим. Вместо него рекомендуется использовать другие механизмы асинхронной работы.
- Использование WorkManager, JobScheduler: Эти компоненты предназначены для выполнения фоновых задач, учитывая ограничения системы и оптимизируя использование ресурсов.
-
AsyncTask позволял выполнять асинхронные операции в фоне и публиковать результаты на главном потоке без необходимости напрямую управлять потоками. Однако начиная с API уровня 30, AsyncTask был объявлен устаревшим из-за ряда недостатков и ограничений.
-
- Утечки памяти: AsyncTask может удерживать ссылку на контекст активности, что может привести к утечке памяти, если активность будет уничтожена до завершения задачи.
- Сложность управления жизненным циклом: AsyncTask не связан с жизненным циклом компонентов UI, что затрудняет управление ресурсами и обновление UI по завершении задачи.
- Ограничения на параллельное выполнение: По умолчанию задачи, выполняемые с помощью AsyncTask, запускались последовательно, что могло замедлять выполнение параллельных операций.
-
- Looper управляет очередью сообщений (Message Queue) для потока. Он зацикливает поток, ожидая входящие задачи (сообщения или выполнимые объекты) и распределяет их для обработки.
- Handler связывает Looper с кодом, позволяя отправлять и обрабатывать сообщения и выполнимые объекты в очереди Looper. Handler может использоваться для обновления пользовательского интерфейса из фонового потока.
- HandlerThread – это вспомогательный класс, создающий поток с собственным Looper, что делает его подходящим для фоновой обработки задач, требующих последовательного выполнения.
-
Утечка памяти в Android происходит, когда объекты, которые больше не нужны приложению, по-прежнему удерживаются в памяти из-за ссылок, не позволяя сборщику мусора очистить их. Это может привести к уменьшению доступной памяти и в конечном итоге к завершению работы приложения.
- Избегайте длительных ссылок на контексты: Используйте контекст приложения, когда это возможно, и избегайте удержания активностей и служб в статических переменных.
- Используйте WeakReference: Когда необходимо удерживать ссылки на объекты, которые могут быть уничтожены, используйте WeakReference.
- Отписывайтесь от слушателей и отменяйте задачи: При уничтожении активности или фрагмента отписывайтесь от слушателей событий и отменяйте фоновые задачи, чтобы избежать удержания ссылок на уничтоженные объекты.
- Можно использовать несколько подходов, включая AsyncTask, Loader, IntentService, HandlerThread. С появлением Kotlin в Android разработке стали популярны корутины для управления асинхронными задачами благодаря их эффективности и простоте использования.
- Основной UI поток (Main Thread) отвечает за обработку пользовательского интерфейса, включая отрисовку элементов на экране и обработку пользовательских взаимодействий. Выполнение длительных операций в главном потоке приводит к "зависанию" приложения и плохому пользовательскому опыту. Асинхронность позволяет выполнять тяжелые задачи в фоновых потоках, не блокируя UI поток.
-
- AsyncTask и Loader: Предоставляют фреймворки для выполнения фоновых задач с возможностью обновления UI по завершении.
- IntentService: Позволяет выполнить операции в фоновом сервисе.
- Handler и Looper: Управление потоками с помощью сообщений и выполнение кода в других потоках.
- Kotlin Coroutines: Современный и эффективный способ для асинхронного программирования, позволяет выполнять асинхронные задачи с минимальными накладными расходами и упрощенным кодом.
- RxJava: Библиотека для композиции асинхронного и событийно-ориентированного программирования с использованием наблюдаемых последовательностей.
-
- SharedPreferences: Легковесный механизм для хранения пар ключ-значение.
- Внутренняя память: Сохранение данных в файловой системе приложения.
- Внешняя память: Использование общедоступного или частного пространства на внешнем носителе.
- SQLite: Встраиваемая база данных для хранения структурированных данных.
- Room: Абстракция над SQLite, упрощающая работу с базой данных и интеграцию с LiveData, Flow для реактивного доступа к данным.
-
Это механизм для хранения и извлечения примитивных данных в виде пар ключ-значение. Используется для сохранения пользовательских настроек или другой небольшой информации, требующей быстрого доступа.
-
Данные, сохраненные в SharedPreferences, хранятся в виде XML-файлов в каталоге /data/data/<package_name>/shared_prefs/. Каждый файл SharedPreferences представляет собой набор пар ключ-значение.
-
- Serializable является стандартным Java интерфейсом и проще в использовании, но медленнее из-за использования рефлексии.
- Parcelable специфичен для Android и требует реализации некоторых методов, но он намного быстрее, что делает его предпочтительным для передачи данных между компонентами Android.
- Json. Использовать одну из любых библиотек по типу gson, moshi, kotlin serialization, jackson и т.д.
-
- Эффективность: Parcelable разработан с учетом эффективности использования памяти и скорости сериализации/десериализации, что критически важно для производительности мобильных приложений.
- Контроль: Разработчик имеет полный контроль над процессом сериализации с Parcelable, что позволяет оптимизировать процесс. Например, можно исключить из сериализации ненужные поля.
- Реализация: Parcelable требует явной реализации методов сериализации, что позволяет избежать использования рефлексии и снижает накладные расходы, связанные с Serializable.
- В целом, использование Parcelable рекомендуется для передачи данных между компонентами Android, особенно если требуется высокая производительность.
-
- Doze — это режим энергосбережения, добавленный в Android 6.0 (Marshmallow), который снижает потребление батареи, ограничивая фоновую активность приложений, когда устройство не используется в течение длительного времени.
- App Standby — это функция, также введенная в Android 6.0 (Marshmallow), которая ограничивает фоновую активность приложений, если пользователь не активно использует эти приложения.
-
Перерисовка (или re-draw) — это процесс, при котором элементы интерфейса пользователя перерисовываются на экране. Это может происходить при изменении данных, которые отображаются в элементе пользовательского интерфейса, или при изменении состояния видимости элемента. Частые перерисовки могут негативно сказаться на производительности и потреблении батареи.
-
Android Runtime (ART) — это среда выполнения приложений для операционной системы Android, которая заменила Dalvik в качестве основной среды выполнения с Android версии 5.0 (Lollipop). ART оптимизирует приложения при их установке, предварительно компилируя их в машинный код, что улучшает производительность и эффективность работы приложений по сравнению с предыдущей системой Dalvik, которая компилировала код во время выполнения приложения (Just-In-Time, JIT компиляция).
-
- Dalvik — это виртуальная машина, используемая в Android до версии 5.0 (Lollipop), которая использовала JIT (Just-In-Time) компиляцию, что означает компиляцию кода приложения в момент его выполнения.
- ART (Android Runtime) — среда выполнения, которая использует подход AOT (Ahead-Of-Time) компиляции, предварительно компилируя приложения в машинный код при их установке, что повышает производительность.
- JIT (Just-In-Time) — метод компиляции, при котором код компилируется в момент его выполнения, а не заранее.
- AOT (Ahead-Of-Time) — метод компиляции, при котором код приложения компилируется в машинный код заранее, при установке приложения, что ускоряет его запуск и работу.
-
Основное различие между Dalvik и ART заключается в методе компиляции. Dalvik использовал JIT компиляцию, компилируя код во время его выполнения, что могло замедлять запуск приложений. ART использует AOT компиляцию, компилируя приложения заранее при их установке, что ускоряет их запуск и улучшает производительность. ART также обеспечивает лучшую управляемость памятью и более эффективное выполнение приложений.
-
DEX (Dalvik Executable) — это формат исполняемых файлов, используемых в Android. Это упакованный файл, содержащий скомпилированный код, который может быть исполнен виртуальной машиной Dalvik или ART. Файлы DEX оптимизированы для минимизации потребления памяти и улучшения производительности на устройствах Android.
-
Multidex — это решение в Android для обхода ограничения Dalvik на максимальное количество методов, которое может быть в одном файле DEX — 65,536. При использовании Multidex приложение может содержать несколько файлов DEX, что позволяет включать больше методов, чем допускает одиночный DEX файл. Это особенно полезно для крупных приложений с большим количеством библиотек.
-
Да, в Android можно вручную вызвать сборщик мусора с помощью метода
System.gc(). Однако следует отметить, что вызов сборщика мусора не гарантирует немедленной очистки памяти. Виртуальная машина Java (JVM) сама решает, когда именно выполнять сборку мусора. Этот метод может использоваться для предложения виртуальной машине выполнить сборку мусора, но без гарантии, что это произойдет немедленно.
-
Android Jetpack – это набор библиотек, инструментов и архитектурных руководств, предназначенный для упрощения разработки приложений. Он предоставляет расширенные компоненты архитектуры, которые помогают построить качественное, тестируемое и модульное приложение. Jetpack ускоряет разработку приложений, помогая автоматизировать повторяющиеся задачи, такие как работа с базой данных, навигация, управление жизненным циклом компонентов и многое другое. Использование Jetpack способствует следованию лучшим практикам, улучшает поддержку различных устройств и версий Android, а также облегчает написание кода, который хорошо работает с основными функциями Android, такими как отложенные задачи и поддержка различных экранов.
-
ViewModel – это компонент архитектуры Android, который предназначен для хранения и управления данными, связанными с пользовательским интерфейсом, прозрачно для изменений конфигурации, таких как поворот экрана. Это позволяет данным пережить пересоздание активности или фрагмента, обеспечивая более эффективное и правильное управление данными UI. ViewModel помогает уменьшить количество кода в активности или фрагменте, связанного с управлением данными, делая архитектуру приложения более чистой, тестируемой и модульной.
-
Компоненты архитектуры Android – это набор библиотек, который помогает разработчикам строить стабильные, тестируемые и поддерживаемые приложения. Включает в себя такие компоненты как LiveData, ViewModel, Room (для работы с базами данных), Paging (для постраничной загрузки данных), WorkManager (для фоновых задач) и многие другие. Эти компоненты предназначены для работы вместе, обеспечивая эффективную и оптимальную разработку приложений.
-
LiveData – это обсервабл-класс данных, который следит за изменениями и уведомляет подписчиков (например, активности или фрагменты) о данных, если эти подписчики находятся в активном состоянии жизненного цикла. Это обеспечивает автоматическое и безопасное управление данными UI, так как данные автоматически обновляются в соответствии с текущим состоянием жизненного цикла компонента.
-
LiveData учитывает жизненный цикл компонентов, автоматически останавливая и возобновляя наблюдение в зависимости от их состояния, что обеспечивает предотвращение утечек памяти и несанкционированного доступа к компонентам UI. ObservableField является частью библиотеки Data Binding и не учитывает жизненный цикл компонентов, что может привести к утечкам памяти, если не управлять подписками вручную.
-
setValue() вызывается в главном потоке и немедленно изменяет данные в LiveData, уведомляя подписчиков. postValue() предназначен для использования из фонового потока и ставит данные в очередь на обновление в главном потоке, что может быть не немедленно.
-
Для общего использования ViewModel между фрагментами можно использовать ViewModelProvider с активностью в качестве области видимости. Это позволяет фрагментам получать экземпляр ViewModel, связанный с их активностью, обеспечивая обмен данными между фрагментами через общую ViewModel.
-
WorkManager – это компонент архитектуры Android, который позволяет гибко управлять фоновыми задачами, учитывая ограничения устройства и системы, такие как состояние заряда батареи или подключение к сети. WorkManager идеально подходит для задач, требующих гарантированного выполнения, например, синхронизация данных, резервное копирование, обработка изображений и т.д., даже если приложение закрыто или устройство перезагружается.
-
ViewModel работает, сохраняя данные в специально отведенном хранилище, которое не уничтожается при изменении конфигурации, таких как поворот экрана. При изменении конфигурации активности или фрагмента, система автоматически пересоздает UI-компоненты, но ViewModel сохраняет свое состояние и данные, делая их немедленно доступными для нового экземпляра UI. Это достигается за счет хранения ViewModel в специализированном хранилище, которое привязано к ViewModelStoreOwner (например, активности или фрагменту), и не зависит от жизненного цикла отдельных компонентов UI.
-
Почему класс
Bundleиспользуется для передачи данных и почему мы не можем использовать простую структуру данных Map?Bundle — это специализированная структура данных, предназначенная для передачи данных между компонентами приложения (например, между активностями). Основные причины использования Bundle вместо Map:
- Сериализация: Bundle может легко сериализоваться и десериализоваться системой Android, что важно для передачи данных между процессами.
- Типизированные методы доступа: Bundle предоставляет типизированные методы для доступа к данным, что упрощает извлечение и хранение данных без явного приведения типов.
- Интеграция с Android: Bundle тесно интегрирован с Android Framework, особенно с компонентами, такими как Intents и Fragments, что облегчает работу с данными в различных частях приложения.
-
- Логирование и анализ: Используйте инструменты логирования (например, Logcat) и аналитики (например, Firebase Crashlytics) для выявления и анализа сбоев.
- Отладка: Применяйте отладчик для пошагового выполнения кода и выявления источника проблемы.
- Тестирование: Разрабатывайте и запускайте тесты (юнит-тесты, интеграционные, UI-тесты), чтобы проверить исправление и обнаружить другие потенциальные проблемы.
- Обновление зависимостей: Убедитесь, что все используемые библиотеки и SDK обновлены до последних версий.
- Пользовательская обратная связь: Отслеживайте отзывы пользователей для выявления сбоев, которые не были обнаружены во время тестирования.
-
- Serializable: Стандартный механизм Java для сериализации объектов. Прост в использовании, но менее эффективен, так как использует рефлексию и создает много временных объектов.
- Parcelable: Механизм сериализации, специфичный для Android, оптимизированный для быстрой передачи данных между компонентами. Требует явной реализации методов сериализации, но работает значительно быстрее Serializable.
Хотя Serializable проще в реализации, Parcelable является предпочтительным выбором для Android из-за его высокой производительности, особенно при передаче сложных объектов между компонентами.
