1*. Жизненный цикл Activity и Fragment 2*. Порядок вызовов onActivityResult и onStart в activity и fragment 3. Порядок вызова onSaveInstanceState 4. То же для fragment внутри Fragment(State)PagerAdapter 5. PagerAdapter: instantiateView, destroyView 6*. Где находится и что делает main 7*. Что такое Looper, Handler, Message, MessageQueue, основные message 8*. launchMode и аналогичные Intent-флаги [https://medium.com/@iammert/android-launchmode-visualized-8843fc833dbe] 9*. Как организовать deep link [смотри 31] 10*. Поля filter, data, action, category в Intent [intent-filter проверяется так: проходит, если хотя бы один action у интента совпадает с фильтром, далее идет тест на category - проходит, если все категории интента являются подмножеством категорий фильтра, затем data - разные правила обработки URI и MIME type; https://developer.android.com/guide/components/intents-filters?hl=en] 11*. Явные и неявные intent [явные - указывают конкретный класс Activity, Service для запуска, неявные - указывают action-строку для выбора подходящего Activity для запуска (или exported-сервиса). 12*. PendingIntent [системный токен, сравнивается с другими через Intent.filterEquals(), описывает Intent(s) и дает другому приложению выполнить эти Intent(s) с разрешениями нашего приложения, запустить броадкаст или сервис] 13*. Как работает prefetch в RecyclerView [https://medium.com/google-developers/recyclerview-prefetch-c2f269075710 ; UI thread в RecyclerView во время скролла должен пройти 4 фазы, чтобы показать новые элементы: Input, Animation, Layout, Record Draw и сделать все это втечение одного кадра. Input это пользовательский код - по-сути связывание данных с view, Record Draw - передача команд на отрисовку в параллельный Render thread. Дальше UI thread испытывает idle до следующего кадра. Или же фаза input занимает слишком много времени, так что Render thread не успевает отрисовать до наступления следующего кадра, и кадры приходится пропускать. Оказалось, что свободное время idle UI thread может использовать для прохождения фазы input следующего кадра. Это и есть prefetch. На скроллинг RecuclerView система запускает runnable в UI потоке, который подгружает (prefetch) новые элементы, в зависимости от направления скрола и layout-manager-а, и выполняет input фазу для них. Система отслеживает среднее время на create/bind данного viewType и пытается предсказать, сколько новых элементов нужно prefetch-ить. Можно задать значение через LinearLM.setInitialItemPrefetchCount(), особенно полезно для вложенных RecyclerView, которые вложены в другие RecyclerView: RecyclerView подгружает свои дочерние элементы по-требованию, а значит для вложенных RecyclerView чтобы заработал prefetch, нужно установить лимит вручную.] 14. Как работает fitsSystemWindow 15. Принципы реализации своих onMeasure и onLayout 16*. Аргументы конструктора View 17. Порядок наложения аттрибутов View 18*. Ссылочные аттрибуты View в темах 19*. Свои аттрибуты для View, получение, различение ссылки и значения 20*. Ссылочные аттрибуты темы в ресурсах - разрешение непрямых ссылок в версии 21+, и как действовать до версии 21 21*. Аттрибуты ConstraintLayout 22. Behavior - основные методы и принципы их реализации 23*. Static и Runtime permissions, классификация: Dangerous, Normal, Signature, Special [Signature - разрешения, при которых приложение В имеет доступ к частям приложения А, защищенным этими разрешениями, должно быть подписано тем же сертификатом, что и приложение А. Обычно применяется приложениями прошивки и самой ОС. Dangerous разрешения с версии М теперь запрашиваются в runtime, до версии М - в диалоге при установке приложения. Список всех разрешений из каждой либо мерещится в Manifest.] 24. Doze mode на разных версиях 25. Основы Dalvik, 65k methods limit, multidex 26. Основы ART, отличия от Dalvik 27*. Аннотации и их retention [CLASS (BINARY) - сохраняются компилятором в .class-файлы, но отбрасываются JVM. Нужны для использования аннотаций из 3rd-party библиотек.] 28*. Основные классы: ContentProvider (+ FileProvider), его authority [служит для доступа к данным различными приложениями, шаринга данных между приложениями. Например: календарь, список контактов, изображения галереи. Запрос в форме URI делается через ContentResolver и по authority (host name + port number) URI система находит подходящий ContentProvider с тем же атрибутом authority. FileProvider это подкласс ContentProvider для безопасного доступа приложений к файлам на девайсе, и использованием схемы content:// вместо схемы file://, т.к при доступе по схеме content:// к файлу генерируются временные права доступа на чтение (запись), а при доступе по схеме file:// нужно вручную задавать права доступа к файлу в самой файловой системе, что а) не-удобно, б) может требовать root привилегии, в) делает файл доступным сразу для всех приложений в системе (что не безопасно). В XML под тегом указываются пути к папкам и файлам, для которых нужно будет сгененировать content://URI с правами доступа к файлам по запросу через FileProvider.] 29. BroadcastReceiver и LocalBroadcastReceiver 30. Service, IntentService, binding, exported-флаг [exported-флаг: true означает открытость сервиса для вызова из других приложений, наличие хотя бы одного intent-фильтра проставляет флаг в true по умолчанию, https://developer.android.com/guide/topics/manifest/service-element] 31. Реализация диплинков, интент-фильтры, onNewIntent, либа от Airbnb 32. Обработка пушей: firebase, onesignal, нотификации и каналы 33*. Изолированность и безопасность приложений друг от друга [каждое приложение в Linux запускается в своем процессе, для которого генерируется пользователь, и только он имеет права доступа к процессу и файлам в insternal-storage директории приложения. ОС запрещает доступ к данным для других приложений.] 34. Старт программы от процесса zygote к activity.onCreate() - как посылается первый интент launcher 35*. Общение между service и activity [через intent] 36*. Как рисуются view, парсинг xml, внутренняя иерархия view, decor view, window, onDraw, invalidate [XMLParser парсит XML в runtime, когда нужно сделать inflate(). Определяется иерархия всех view. Делается проход по иерархии алгоритмом DFS, каждый ParentView передает вниз своим ChildView значения measureSpec - ограничения по размерам, и вызывает на них measure()-метод или его производные (можно передать как measureSpec, так и layoutParams через AttributeSet). ChildView в свою очередь получает коллбек onMeasure(), в котором вычисляет свои желаемые размеры и делает reconcileSize() со значениями measureSpec от ParentView, и вычисляет свои итоговые размеры, передавая их назад в ParentView через метод setMeasuredDimensions(). После измерений своих детей, родитель этого ParentView вызывает layout(), а сам ParentView получает коллбек onLayout(), в который приходят пиксельные координаты текущего ParentView в его родителе. В onLaoyut() ParentView должен позиционировать каждый ChildView, используя свои и их паддинги, а также марджины из layoutParams каждого чилда, и вычислив координаты чилда, вызвать на каждом их них layout(). ViewGroup обязан определить onLayout(), а просто View в общем случае должен определить только onDraw() для рисования контента вьюхи на Canvas с помощью кистей. Порядок вызовов такой: onMeasure() -> onLayout() -> onDraw(), dispatchDraw() вызывается на родителе, чтобы дать команду чилду вызывать onDraw(). При каждом изменении контента вьюха должна вызывать invalidate() или его производные, чтобы перерисовать контент. Жизненный цикл вью, onAttachedToWindow() вызывается после onResume() в ActivityThread.handleResumeActivity() НО только 1 раз за ЖЦ Activity, который добавляет DecorView в WindowManager, а затем этот DecorView зовет WindowManagerGlobal.addView(), которых обходит всю иерархию вьюх и вызывает у каждого onAttachedToWindow(), onDetachedFromWindow() вызывается в Activity.onDestroy(); https://codentrick.com/android-view-lifecycle/; https://www.youtube.com/watch?v=4NNmMO8Aykw] 37. Отличия width, measuredWidth, suggestedWidth 38. Обработка touch, от activity до view 39*. post и runOnUiThread [отправляет runnable в Handler, привязанный к Looper, привязанный к MainThread] 40. FragmentManager: transaction, commit, commitNow, commitAllowingStateLoss, запрпт нажатий после onStop в новых версиях, backStack 41. onConfigurationChange, конфигурации activity 42. onTouch-event и основные нажатия 43. Как работает butterKnife внутри 44*. Работа с галереей и камерой, contentProvider [смотри 28] 45. Google play services: проверка наличия, локация gps, авторизация, map, google pay 46. Wake lock и отладка, alarm manager, посылка и обработка уведомлений по расписанию 47. AlarmManager, SyncManager, JobScheduler, WorkManager 48. StrictMode 49*. dumpsys, systrace, отладка лагов при отрисовке [отладка ANR производится через файл data/traces.txt, в котором следует искать причину блокировки главного main потока; systrace - показывает производительность отрисовки view, он запускается в консоли на временной интервал, во время которого нужно произвести действия в приложении, затем открыть полученный HTML в Chrome и приближая вид, найти места с избыточной или медленной отрисовкой, Race-Блоки в коде добавляют метки в отчет systrace (https://developer.android.com/studio/command-line/systrace); dumpsys - инструмент диагностики системных сервисов на девайсе.] 50. Отладка утечек памяти, различные примеры порождения утечки памяти, как работает LeakCanary 51. Команды adb: установка и удаление апки, запуск апки, посылка интента, поиска апки по package 52. Internal и external memory 53. Manifest merging, ссылки из gradle, разрешения и ресурсы 54. Диаграмма блоков памяти apk, что оптимизируют, string-block 55. Сократить размер файла apk 56. Основные директивы ProGuard, варнинги и рефлексия 57. Gradle: 3 стадии сборки [Initialization - гредл создает обьекты Project для всех модулей, которые будут участвовать в сборке, изучается файл settings.gradle. Configuration - конфигурируются объекты Project и выполняется блок allProjects, задаются таски, их имена и аргументы, выполняется код в телах танков ВНЕ замыканий. Execution - выполняются таски, которые не up to date, https://docs.gradle.org/current/userguide/build_lifecycle.html] 58. Gradle: блоки buildscript, allprojects, dependencies, repositories, android 59. Gradle plugins 60. Конфиги compile, provided, apk, runtime, implementation, compileOnly, runtimeOnly, api, зависимости между модулями, транзитивность, ресурсы aar, исключения, группы и артефакты 61. Тестовые конфиги: test*, androidTest 62. annotationPeocessor, apt, kapt 63. Конфликты между либами, dependency insight, exclude, замещение по умолчанию 64. Сокращение количества методов в apk 65. Таски gradle: assemble, build, test, clear 66. Свои таски в gradle 67. Блок android: основные поля и замыкания 68. Product flavors 69*. Определение своих переменных в gradle [buildConfigField, "type", "name", "value"] 70. gradle build-tools, что содержат, android (edited) 71. Методы ускорения сборки, модуларизация (бенчмарк, зависимости для пересборки), gradle daemon 72*. Dagger2: основные сущности и базовые реализации, provider, lazy, subcomponent [https://medium.com/@elye.project/dagger-2-for-dummies-in-kotlin-subcomponent-5a969b6aec7a ; subcomponent - компонент, который можно получить из родительского component, так как запрещено иметь вложенные components. Scope у subcomponent может отличаться от scope родительского component. Используются также для изоляции отдельных компонент в программе. Объекты живущие в subcomponent могут зависеть от объектов своего модуля и в родительский (sub)components, но не в sibling subcomponents. Если объекту требуется зависимость, которой нет в модуле проводящего этот объект компонента, можно либо сделать includes в модуль и расширить список объектов модуля, либо сделать компонент этого объекта субкомпонентом другого компонента, проводящего нужную зависимость. Эти подходы похожи, но субкомпоненты организуют лучший decoupling. ; https://proandroiddev.com/dagger-2-part-three-new-possibilities-3daff12f7ebf ; Provider, T - класс предоставляемого даггером объекта (зависимость) - интерфейс, используемый для отложенного получения зависимости (объекта класса Т), до первого вызова .get(), однако каждый вызов .get() будет создавать новый объект Т, невзирая на scope этого T или scope производящего его метода в модуле. Такое поведение может понадобиться, когда нужно получать некий объект в разных местах программы, а его значение меняется по ходу программы, и каждый раз надо получить актуальное его значение. Lazy - та же отложенная инициализация, но объект будет кешированный внутри и каждый последующий вызов .get() будет возвращать прежний объект Т. Объект Т закешированный внутри Lazy, поэтому если создать другой экземпляр Lazy хоть и для того же объекта Т, то .get() на этом другом Lazy приведет к созданию объекта Т, так как кеши у обоих Lazy предполагаются различными и независимыми. Объект Т будет единым для разных Lazy, если проводящий его метод модуля помечен через Scope, например Singleton. Также можно сделать создание зависимостей асинхронным - например, когда какой-нибудь объект инициализируется ресурсоемко - можно в модуле помимо scoped-провайд-метода этого объекта сделать еще и провайд-метод Observable этого же объекта, который будет вызывать fromCallable(Lazy::get(), если же убрать scope у провайд-метода и заменить Lazy на Provider, можно асинхронно создавать множество объектов Т.] 72*. Dagger выше 2.7, builder, модуль с субкомпонентами, и т.д [теперь можно писать свой Component.Builder - создавая интерфейс, аннотированный @Component.Builder и обязательно имеющий метод build(). Раньше builder() был задан либо и имел только методы *module() и *component(). Как и раньше, можно задать модули, а еще можно добавить объекты, которые будут видны в графе, для этого в интерфейсе Component.Builder нужно будет создать методы @BindsInstance - эти методы связывают типы в графе (возвращаемые значения методов) с переданными в эти методы объектами. Их можно использовать во всем графе, расширяя такое поведение, когда можно было только передать объекты в модуль и они были видно только в этом модуле. Также используются в графе, чтобы не дублировать одни и те же параметры при передаче в каждый модуль, где они требуются, а определив их сразу на весь граф и во все модули. ; @Reusable аннотация - промежуточное между scope и unscoped. В рамках одного компонента такие объекты являются scoped, но для разных компонент будут кешированы разные экземпляры объекта @Reusable. Эта ситуация достигается тогда, когда есть родительский компонент с @Reusable объектом и два субкомпонента, каждый из которых будет иметь свой закешированный экземпляр этого @Reusable. ; https://proandroiddev.com/dagger-2-part-three-new-possibilities-3daff12f7ebf ; @Binds аннотация заменяет аннотацию @Provides, когда провайд-метод просто возвращает входной аргумент как результат: в этом случае тело метода можно опустить и сделать метод (и весь модуль) abstract, что также улучшит перфоманс (наряду с использованием static провайд-методов), создание всех зависимостей для @Binds-объекта подразумевается через @Inject-конструкторы (методы) и прочие способы. ; multibindings - @Provides(Type.SET), @Provides(Type.MAP) + @Key - позволяет внедрять Set и Map объектов, провайд-методы должны быть аннотированы и возвращать конкретную реализацию объекта.] 73. Dagger2 для Android: вспомогательные классы [https://proandroiddev.com/dagger-2-annotations-binds-contributesandroidinjector-a09e6a57758f ; ] 74*. Dagger2 внутри, время жизни обьектов, scopes, qualifiers 75*. Lazy инициализация для компонентов во фрагменте, использование provider в коде 76*. Rx observable contract [http://reactivex.io/documentation/contract.html] 77*. Сущности: observable, flowable, subscription / disposable, single, maybe, completable, subject'ы 78*. Порядок выполнения операторов в потоках, внутренние потоки rx [producer событий и все операторы выполняются в вызывающем потоке, если в цепочке нет subscribeOn(), который переводит в другой поток все операторы до и после него, до следующего subscribeOn() или observeOn(), последний переводит в свой поток все операторы и коллбеки подписки, следующие после него.] 79*. Основные операторы [flatMap - из событий производит observable трансформированных событий, так что вся последующая цепочка операторов и коллбеки теперь срабатывают на этом новом observable. flatMap использует merge для событий исходного observable, так что они могут interleave. concatMap использует concat, что сохраняет исходный порядок событий, но при этом оператор ждет пока не закончится предыдущая эмиссия прежде чем начать следующую. switchMap - эмитит только самое последнее событие, отписываясь от всех внутренних observables, которые были сгенерированы и излучили раньше. Не возвращает их результат. flatMap и аналоги полезен, когда события исходного observable имеют в себе или могут быть трансформированы каждый в отдельный observable, так что можно будет получить аккумулированный результат их работы в виде последовательности событий одного итогового observable. Пример - сетевой запрос, для каждого ответа на который надо сделать еще один сетевой запрос, и затем все результаты обработать дальше по цепочке ; https://medium.com/appunite-edu-collection/rxjava-flatmap-switchmap-and-concatmap-differences-examples-6d1f3ff88ee0 ; debounce - эпитет последнее событие, произошедшее в пределах интервала по прошествии этого интервала, throttleFirst (Last) - sample - эпитет только самый ранний (поздний) событие произошедшее в пределах интервала] 80*. Backpressure, hot и cold observables [Cold - излучает события только когда observer подписывается на него (этот observable) через вызов subscribe(). Каждый новый observer, подписывающийся на cold observable будет получать те же самые события, начиная с самого первого, что и исходный подписчик observer: функция, производящая события, будет инициализироваться сначала и вызываться повторно при каждой новой подписке. Hot - излучает события с момента своей инициализации (активации), т.е. независимо от наличия подписок на него. Функция, производящая события, продолжит выполняться дальше, когда возникнет первая подписка, и эта подписка получит очередное событие от функции, а не самое первое значение. Можно считать, что producer событий инициализируется внутри Observable.create {} для Cold, и снаружи для Hot. Hot позволяет иметь множество подписок на одни и те же события. Создать Hot можно из Cold с помощью publish() - это создает внутренний Subject, подписанный на исходный Cold, и затем уже можно будет подписать всех остальных подписчиков на этот Subject (обернутый в ConnectableObservable). Вызов connect() сразу запускает излучение событий, autoConnect(n) ждет пока наберется n подписчиков, refCound() ждет когда наберется первый подписчик и отпишет внутренний Subject от излучателя событий когда все остальные подписчики отпишутся (ref count станет 0) тем самым освобождая ресурсы излучателя. share() == publish().refCount(). Есть еще методы повтора всех предыдущих событий для каждого нового подписчика - replay(); https://github.com/ReactiveX/rxjs/issues/2604, https://blog.thoughtram.io/angular/2016/06/16/cold-vs-hot-observables.html, https://medium.com/@benlesh/hot-vs-cold-observables-f8094ed53339 ; Backpressure - накопление событий от observable к observer, при условии что observer обрабатывает их медленнее, чем observable их излучает, так что нужна политика разрешения (иначе будет MissingBackpressureException) - одна из ignore, buffer, discard, last, ... По-умолчанию имеется внутренний буфер на 16 или 100 событий. Политика missing подразумевает, что следующий оператор или observer будут поддерживать некоторую другую политику по backpressure. Observer.request(n) посылает нотификацию в подписанный observable о том что observer ждет не более n событий, а Observable.onSubscribe уведомляет о готовности выполнить request]. 81*. Rx1 vs Rx2 [Rx2: больше нельзя отправлять null значения, Flowable - это Observable, обрабатывающий backpressure по-умолчанию, Disposable - это бывший Subscription, а Subscription теперь интерфейс, позволяющий запросить некоторое количество событий или остановить цепочку, 82*. fromCallable, just [https://www.lvguowei.me/post/rxjava-fromcallable-vs-defer/; just() - просто вычисляет значение и формирует из него событие, которое будет излучено при последующей подписке. Важно то, что вычисление происходит сразу же, т.е. если producer значения - сетевой запрос - он будет выполнен сразу же (в главном потоке), просто его значение будет обернуто в observable и излучено в момент подписки. Чтобы вычислять значение именно в момент подписки, нужно использовать defer() { just() } или fromCallable {}] 83*. RxBindings 84. Retrofit и retrofit2, отличия, как работают внутри (какие потоки), на какие сервисы опираются 85. Room: сущность, таблица, dao, foreignKey, взаимосвязи между таблицами, уровни вложенности 86. Sql: join и другие методы 87. Realm: обьекты, жизненный цикл, конфигурации, дебаг (null обьекты), уровни вложенности, операции над обьектами, именование полей, миграции, nullability 88. Особенности при работе с rx и бд 89*. Архитектура mvp [SOLID - S - одна роль класса, O - классы открыты для расширения и закрыты для модификации, L - объекты базовых классов могут быть заменены на объекты производных классов прозрачно, I - интерфейсы должны быть простейшими, D - модули верхнего уровня не должны зависеть от модулей нижнего уровня, и все модули должны зависеть от интерфейсов, снижает связность-хрупкойсть.] 90. Mvvm старый и его компоненты 91. Mvvm из arch components 92. Clean arch 93. Mosby framework 94. Moxy framework, viewState 95. Repository, получение данных offline-mode, получение данных из облака-затем-кеш 96. Kotlin: операторы, inline и extension методы, in out вариантность, sealed class, coroutines 97. Type erasure в java 98. Алгоритмы и структуры данных, DFS, BFS 99. Потоки, thread, threadPoolExecutor, interruptedException и interrupt-флаги, механизм выхода из блокирующего метода через checked-ioException 100. Garbage collection, модель памяти jvm