tgoop.com »
United States »
Библиотека мобильного разработчика | Android, iOS, Swift, Retrofit, Moshi, Chuck » Telegram Web
Please open Telegram to view this post
VIEW IN TELEGRAM
😁10
Представь: ты на собеседовании мечты, и тут HR спрашивает про зарплату. Что скажешь? Называешь число первым или ждешь? Завышаешь или играешь честно? Мы собрали 9 работающих стратегий с конкретными примерами фраз — от «Открытой» до «Я никуда не тороплюсь». Выбирай свою и перестань продавать себя дешево.
#MadeInProglib
Please open Telegram to view this post
VIEW IN TELEGRAM
Приготовили для вас дайджест по актуальному из мира iOS, Android.
В этой статье автор систематизирует Mobile System Design как дисциплину: покажет, какие навыки действительно важны и как они проверяются. Это не личное мнение, а выжимка из опыта инженеров, требований собеседований, литературы и практики команд.
В статье будет гремучая смесь из Java, C#, NodeJS, Swift, bash, Dockerfile и github actions. Но в результате возможность непрерывно поставлять свежие сборки в магазины приложений.
Автор расскажет о JSON Schema и как использует эту спецификацию на проекте, а также о библиотеке kotlinx.serialization и том, как она упростила работу со схемами. Статья будет полезна разработчикам, которые интересуются библиотекой kotlinx.serialization и хотят глубже узнать её устройство. В ней обсудим:
В этой статье — краткое сравнение популярных сервисов локализации и разбор подключения TMS по шагам.
#свежак
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2😁1
Полиморфизм представлять возможность взаимозаменяемости типов, которые находятся в одной иерархии классов. Например, возьмем следующую иерархию классов:
class Person{
var name: String
var age: Int
init(name: String, age: Int){
self.name = name
self.age = age
}
func display(){
print("Имя: \(name) Возраст: \(age)")
}
}
class Employee : Person{
var company: String
init(name: String, age: Int, company: String) {
self.company = company
super.init(name:name, age: age)
}
override func display(){
print("Имя: \(name) Возраст: \(age) Сотрудник компании: \(company)")
}
}
class Manager : Employee{
override func display(){
print("Имя: \(name) Возраст: \(age) Менеджер компании: \(company)")
}
}В данном случае класс Manager (менеджер компании) наследуется от класса Employee (сотрудник компании), а класс Employee - от класса Person (человек). Тем самым класс Manager ненапрямую тоже наследуется от Person.
Поскольку и сотрудник компании и менеджер компании в то же время являются людьми, то есть объектами класса Person, то мы можем написать следующим образом:
let tom: Person = Person(name:"Tom", age: 23)
let bob: Person = Employee(name: "Bob", age: 28, company: "Apple")
let alice: Person = Manager(name: "Alice", age: 31, company: "Microsoft")
Все три константы представляют тип Person, однако первая хранит ссылку на объект Person, вторая - на объект Employee, а третья - на объект Manager. Таким образом, переменная или константа одного типа может принимать многообразные формы в зависимости от конкретного объекта, на который она указывает.
Но что будет, если мы вызовем метод
display() для всех трех объектов:let tom: Person = Person(name:"Tom", age: 23)
let bob: Person = Employee(name: "Bob", age: 28, company: "Apple")
let alice: Person = Manager(name: "Alice", age: 31, company: "Microsoft")
tom.display() // Имя: Tom Возраст: 23
bob.display() // Имя: Bob Возраст: 28 Сотрудник компании: Apple
alice.display() // Имя: Alice Возраст: 31 Менеджер компании: Microsoft
Несмотря на то, что все три константы представляют тип Person, при вызове метода display будет вызываться реализация метода именно того класса, ссылку на объект которого хранит константа. Данный примем называется динамической диспетчеризацией - во время выполнения программы на основании типа объекта система решает, какую именно реализацию метода вызывать.
В одной стороны, это нам дает ряд преимуществ - мы можем работать с объектом производного типа как с объектом базового типа и использовать его везде, где требуется объект базового типа. Но с другой стороны, поскольку решение о выборе реализации принимается во время выполнения, то это несколько замедляет общий ход работы программы.
#буст #JuniorKit #Swift
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5🥱1
Красивые мягкие тени делают интерфейс объёмным и аккуратным. В Compose этого можно добиться с помощью
drawBehind, чтобы контролировать цвет, размытие и смещение тени — как в дизайне.@Composable
fun ShadowCard(
modifier: Modifier = Modifier,
content: @Composable BoxScope.() -> Unit
) {
Box(
modifier = modifier
.drawBehind {
drawRoundRect(
color = Color(0x1A000000), // мягкая полупрозрачная тень
cornerRadius = CornerRadius(16.dp.toPx()),
topLeft = Offset(0f, 6.dp.toPx())
)
}
.background(Color.White, RoundedCornerShape(16.dp))
.padding(16.dp)
) {
content()
}
}
Тень выглядит естественно, без резких границ, повторяет форму карточки и не «съезжает» на светлой теме.
ShadowCard(
modifier = Modifier
.fillMaxWidth()
.height(120.dp)
) {
Text("PixelPerfect ", modifier = Modifier.align(Alignment.Center))
}
Такой подход легко адаптировать под любые формы и цвета. Главное — держать параметры тени (смещение, прозрачность, радиус) в синхронизации с макетами из Figma.
#PixelPerfect #JuniorKit #Android
Please open Telegram to view this post
VIEW IN TELEGRAM
Каждый пользователь ненавидит их, каждый продакт их требует, а каждый разработчик… просто хочет, чтобы они доставлялись.
Одни говорят: пуши — это забота о пользователе, напоминание, что приложение живёт. Другие считают: пуши — причина, почему люди удаляют приложения.
И где грань между вовлечением и раздражением?
А ты что думаешь?
❤️ — Отправляю пуши с любовью
👍 — Убираю всё, что трогает юзера без спроса
🤝 — Главное — не переборщить
#междусобойчик
Please open Telegram to view this post
VIEW IN TELEGRAM
🤝4
Android Developer — от 200 000 ₽, гибрид (Санкт-Петербург)
Senior iOS Developer (Swift, SwiftUI, UIKit, CloudKit, APN, Network Extension) — от 500 000 ₽ , удалёнка
Kotlin/Java Developer (JetBrains Platform) — от 300 000 до 370 000 ₽, удалёнка
Senior Flutter-разработчик — от 4 000 до 7 000 $, удалёнка
iOS разработчик — удалёнка
#свежак
Please open Telegram to view this post
VIEW IN TELEGRAM
❤1👍1
В Clean Swift приложение состоит из сцен, т.е. каждый экран приложения — это одна сцена. Основное взаимодействие в сцене идет через последовательный цикл между компонентами ViewController -> Interactor -> Presenter. Это называется VIP цикл.
Мостом между компонентами выступает файл Models, который хранит в себе передаваемые данные. Так же есть Router, отвечающий за переход и передачу данных между сценами, и Worker, который берет часть логики Interactor’a на себя.
🔹 View
Storyboard’ы, XIB’ы или UI элементы, написанные через код.
🔹 ViewController
Отвечает только за конфигурацию и взаимодействие с View. В контроллере не должно находиться никакой бизнес логики, взаимодействия с сетью, вычислений и так далее.
Его задача обрабатывать события с View, отображать или отправлять данные (без обработки и проверок) в Interactor.
🔹 Interactor
Содержит в себе бизнес логику сцены.
Он работает с сетью, базой данных и модулями устройства.
Interactor получает запрос из ViewController’a (с данными или пустой), обрабатывает его и, если это требуется, передает новые данные в Presenter.
🔹 Presenter
Занимается подготовкой данных для отображения.
Как пример, добавить маску на номер телефона или сделать первую букву в названии заглавной.
Обрабатывает данные, получение из Interactor’a, после чего отправляет их обратно во ViewController.
🔹 Models
Набор структур для передачи данных между компонентами VIP цикла. Каждый круг цикла имеет в себе 3 вида структур:
🔹 Worker
Разгружает Interactor, забирая на себя часть бизнес логики приложения, если Interactor стремительно разрастается.
Так же можно создавать общие для всех сцен Worker’ы, если их функционал используется в нескольких сценах.
Как пример, в Worker можно выносить логику работы с сетью или базой данных.
🔹 Router
В Router выносится вся логика, отвечающая за переходы и передачу данных между сценами.
____________________
Для прояснения картины работы VIP цикла приведу стандартный пример — авторизация.
1. Пользователь ввел свой логин и пароль, нажал на кнопку авторизации
2. У ViewController срабатывает IBAction, после чего создается структура с введенными, в TextField’ы, данными пользователя (Models -> Request)
3. Созданная структура передается в метод fetchUser в Interactor’e
4. Interactor отправляет запрос в сеть и получает ответ об успешности авторизации
5. На основе полученных данных, создает структуру с результатом (Models -> Response) и передается в метод presentUser в Presenter’e
6. Presenter форматирует данные по необходимости и возвращает их (Models -> ViewModel) в метод displayUser в ViewController’e
7. ViewController отображает полученные данные пользователю. В случае с авторизацией, может выводиться ошибка или срабатывать переход на другую сцену с помощью Router
Таким образом, мы получаем единую и последовательную структуру, с распределением обязанностей на компоненты.
#АрхитектурныйКод #SeniorView #Swift
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3
Please open Telegram to view this post
VIEW IN TELEGRAM
😁8
KMP Starter — современный, готовый к использованию шаблон приложения на Kotlin Multiplatform с дизайном Material 3, утилитами и чистой архитектурой.
Технический стек: Kotlin Multiplatform для кроссплатформенной разработки, Compose Multiplatform для UI, Material 3 как дизайн-система, Koin для инъекции зависимостей, Room в качестве локальной базы данных, DataStore для хранения настроек, корутины и Flow для асинхронного программирования, RevenueCat для покупок, MixPanel для аналитики, Kotlinx Serialization для сериализации JSON.
#буст #Android
Please open Telegram to view this post
VIEW IN TELEGRAM
❤1
В карточках рассказали, как устроены эти системы, какие из них используют российские и зарубежные IT-компании, и главное — как адаптировать резюме, чтобы робот тебя пропустил.
#MadeInProglib
Please open Telegram to view this post
VIEW IN TELEGRAM
VK Звонки способны работать даже в условиях высокой потери пакетов и низкой пропускной способности сети. Хотя интернет в крупных городах стал быстрым и стабильным, поездки в метро, использование лифта или подключение к Wi-Fi в кафе по-прежнему создают проблемы с качеством связи.
Спикеры рассказали, как решили эту задачу на Android-клиенте и какие техники для аудио и соединения можно применить в вашем проекте для звонков.
Доклад будет полезен всем, кто хочет узнать о передаче медиа в реальном времени в сложных сетевых условиях.
#свежак
Please open Telegram to view this post
VIEW IN TELEGRAM
😁4👾1
adb shell dumpsys meminfo – детальный анализ использования памяти приложениемМощный инструмент для мониторинга использования памяти вашим приложением в реальном времени. Помогает находить утечки памяти и оптимизировать потребление RAM.
1. PSS (Proportional Set Size):
• Реальная память, занимаемая приложением
• Включает разделяемую память (пропорционально)
2. Private Dirty:
• Память, принадлежащая только вашему приложению
• Не может быть выгружена в swap
3. Java Heap:
• Память, управляемая Dalvik/ART
• Ключевой показатель для поиска утечек
Мониторинг в реальном времени:
# Каждые 2 секунды обновлять информацию
watch -n 2 "adb shell dumpsys meminfo com.yourapp.package"
Сравнение состояний:
# До и после выполнения операции
adb shell dumpsys meminfo com.yourapp.package > before.txt
# Выполняем действия в приложении
adb shell dumpsys meminfo com.yourapp.package > after.txt
diff before.txt after.txt
Поиск утечек в Activity:
# Проверить, не остались ли Activity в памяти
adb shell dumpsys meminfo | grep -E "Activity|View|Context"
Только Java Heap:
adb shell dumpsys meminfo com.yourapp.package | grep -A 10 "Java Heap"
Нативные allocations:
adb shell dumpsys meminfo com.yourapp.package | grep -A 5 "Native Heap"
Applications Memory Usage (in KB)
Uptime: 1234567 Realtime: 1234567
** MEMINFO in pid 1234 [com.yourapp] **
Pss Private Private SwapPss Heap Heap Heap
Total Dirty Clean Dirty Size Alloc Free
------ ------ ------ ------ ------ ------ ------
Native Heap 12345 12000 345 100 15000 14000 1000
Dalvik Heap 5678 5600 78 50 6000 5800 200
🔧 Продвинутое использование:
Профилирование конкретной операции:
#!/bin/bash
echo "Память до:" > mem_log.txt
adb shell dumpsys meminfo com.yourapp.package >> mem_log.txt
# Запускаем тестовый сценарий
adb shell am start -n com.yourapp/.TestActivity
echo "Память после:" >> mem_log.txt
adb shell dumpsys meminfo com.yourapp.package >> mem_log.txt
Pro-совет: Используйте с procstats для долгосрочного мониторинга:
bash
adb shell dumpsys procstats --hours 1 com.yourapp.package
Как вы отслеживаете использование памяти в своих приложениях?
#буст #MiddlePath #Android
Please open Telegram to view this post
VIEW IN TELEGRAM
❤2
Please open Telegram to view this post
VIEW IN TELEGRAM
Почему счетчик лайков увеличивается неправильно при быстром нажатии?
Anonymous Quiz
28%
Кнопка не блокируется во время анимации
10%
Неправильная работа с состоянием likeCount
35%
Отсутствие debounce для быстрых нажатий
5%
Проблема с анимацией transform
22%
Посмотреть ответ
