Android Mobile | YeaHub
430 subscribers
332 photos
21 videos
597 links
Теория, подготовка к интервью и курсы для Android разработчиков

YeaHub — это платформа для IT-специалистов, объединяющая обучение, карьерный рост, развитие и сообщество единомышленников.

Платформа: https://yeahub.ru

Для связи: @ruslan_kuyanets
Download Telegram
#ЧеКак
🤔 Какой минус есть у виртуальных таблиц?

Виртуальные таблицы, такие как те, что используются в SQLite с помощью CREATE VIRTUAL TABLE, предлагают мощные возможности для работы с данными. Однако они также имеют некоторые недостатки.

🟠Ограниченная поддержка стандартных функций SQL
Виртуальные таблицы могут не поддерживать все стандартные функции и возможности SQL, такие как ограничения (constraints), триггеры и определенные типы индексов. Это связано с тем, что их функциональность определяется модулем, который реализует виртуальную таблицу.
CREATE VIRTUAL TABLE my_virtual_table USING fts4(content TEXT);


🟠Производительность
Виртуальные таблицы могут иметь производительность ниже, чем обычные таблицы, особенно если они не оптимизированы должным образом. Производительность может пострадать из-за дополнительных накладных расходов, связанных с обработкой виртуальных таблиц на уровне приложения или расширений.

🟠Сложность реализации и обслуживания
Использование виртуальных таблиц требует дополнительных знаний и опыта в разработке и обслуживании. Например, вам может потребоваться написать и поддерживать специализированные модули или расширения для реализации виртуальных таблиц, что увеличивает сложность кода и потенциальные затраты на поддержку.

👉Новости 👉Платформа
Please open Telegram to view this post
VIEW IN TELEGRAM
#ЧеКак
🤔 Что такое мульти-декларации (destructuring declarations)?

Это способ извлечения значений из объекта и присвоения их сразу нескольким переменным. В Kotlin этот механизм поддерживается с помощью оператора распаковки (destructuring operator) — componentN(), где N — номер компонента.

При создании data класса Kotlin автоматически создает функции componentN() для каждого свойства класса, где N — номер позиции переменной в конструкторе. Функции componentN() возвращают значения свойств в порядке их объявления в конструкторе. Это позволяет использовать мульти-декларации для распаковки значений свойств и присваивания их отдельным переменным.

🚩Пример

Если у нас есть data класс Person с двумя свойствами name и age, мы можем использовать мульти-декларации, чтобы извлечь эти свойства и присвоить их двум переменным:

data class Person(val name: String, val age: Int)

val person = Person("Alice", 29)
val (name, age) = person

println(name) // Alice
println(age) // 29

Также можно использовать мульти-декларации в циклах, чтобы итерироваться по спискам объектов и распаковывать значения свойств:


val people = listOf(Person("Alice", 30), Person("Bob", 40))
for ((name, age) in people) {
println("$name is $age years old")
}

// Alice is 30 years old
// Bob is 40 years old


Мульти-декларации также могут быть использованы с массивами и другими коллекциями:

val list = listOf("apple", "banana", "orange")
val (first, second, third) = list

println(first) // apple
println(second) // banana
println(third) // orange


👉Новости 👉Платформа
Please open Telegram to view this post
VIEW IN TELEGRAM
#Вакансии
👨‍💻 Android Developer

Локация: Удалённо в РФ
Компания: Effective
ЗП: до 300 000 р. на руки
Занятость: Полная
Требуемый опыт работы: 3+ лет

Effective – IT компания, специализирующаяся на заказной mobile и web-разработке высококачественных цифровых сервисов и продуктов для Retail, Telecom и B2G бизнесов.

🚩Мы ожидаем от тебя
▪️Глубокое понимание Kotlin и Android;
▪️Опыт разработки UI компонентов с Compose и/или View;
▪️Опыт работы в многомодульных проектах. Умение применять RxJava 2 и Flow;
▪️Применение принципов Dependency Injection (Dagger 2);
▪️Опыт работы с Coroutines.

🚩Будет плюсом
▪️Написание unit-тестов и опыт написания автотестов для Android (Espresso/Kaspresso);
▪️Опыт написания автотестов с подменой ответов бэкенда (моки);
▪️Работа с инструментами для тестирования серверного API (Postman, SoapUI).

🚩Предстоящие задачи
▪️Работа в команде над разработкой Android приложения;
▪️Подключение к покрытию мобильных приложений автотестами;
▪️Автоматизация и поддержка сценариев тестирования в Android приложении;
▪️Необходимо писать авто тесты, оптимизировать и ускорять сами автотесты, дорабатывать CI-пайплайны;
▪️Писать и дорабатывать PageObject-ы для экранов;
▪️Дорабатывать тестовую систему для поддержки новых элементов и взаимодействия с ними;
▪️Дорабатывать тестовую инфраструктуру.

🚩От нас
▪️Работа в аккредитованной IT компании;
▪️Лояльные руководители и отсутствие бюрократии;
▪️Performance review: регулярный фидбек от тимлидов, понимание зон роста, помощь в развитии в интересном направлении;
▪️Work-life balance: поддержка и компенсация обучения и здорового образа жизни;
▪️Ежегодные путешествия с командой: расширяем географию и завоевываем новые вершины, разделяем прекрасные моменты вместе;
▪️Совместные времяпровождения: Happy Friday & Monthly Stand-up, участие во внутренних мероприятиях и инициативах. Разделим интерес каждого и найдем хобби по душе;
▪️Smart-мероприятия для сотрудников как внутри компании и города, так и за пределами: мы организовываем Student Labs, DevFest для Senior-разработчиков

💬 Резюме отправлять: @Vitaly_Researcher

👉Новости 👉Платформа
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔 Как в Kotlin обозначается безопасное приведение типа, которое не вызовет исключение при неудаче?
Anonymous Quiz
11%
as
0%
is
89%
as?
0%
safeCast
#ЧеКак
🤔 В чём различия наследования, композиции, агрегации?

Наследование предполагает создание нового класса на основе существующего. Композиция включает один класс в качестве части другого для использования его функциональности. Агрегация — слабая форма композиции, где включённый объект может существовать независимо от владельца.

👉Новости 👉Платформа
Please open Telegram to view this post
VIEW IN TELEGRAM
#ЧеКак
🤔 Как бы реализовал приложение, которое может загружать большие файлы на сервер?

Для реализации приложения, которое загружает большие файлы на сервер, необходимо учитывать несколько аспектов, таких как асинхронная обработка, устойчивость к изменениям конфигурации, восстановление после неудачных попыток загрузки и отображение состояния загрузки пользователю.

1⃣Настройка зависимостей
В файле build.gradle вашего модуля добавьте следующие зависимости:
dependencies {
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'androidx.work:work-runtime-ktx:2.7.1'
}


2⃣Настройка Retrofit
Создайте интерфейс для API и настройте Retrofit.
// UploadAPI.java
public interface UploadAPI {
@Multipart
@POST("/upload")
Call<ResponseBody> uploadFile(@Part MultipartBody.Part file);
}

// RetrofitClient.java
public class RetrofitClient {
private static Retrofit retrofit = null;

public static Retrofit getClient(String baseUrl) {
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}


3⃣Создание Worker для загрузки файла
Используйте WorkManager для загрузки файла в фоновом режиме.
// FileUploadWorker.java
public class FileUploadWorker extends Worker {

public FileUploadWorker(@NonNull Context context, @NonNull WorkerParameters params) {
super(context, params);
}

@NonNull
@Override
public Result doWork() {
String filePath = getInputData().getString("file_path");
if (filePath == null) {
return Result.failure();
}

File file = new File(filePath);
RequestBody requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), file);
MultipartBody.Part body = MultipartBody.Part.createFormData("file", file.getName(), requestFile);

UploadAPI api = RetrofitClient.getClient("https://yourserver.com/").create(UploadAPI.class);
Call<ResponseBody> call = api.uploadFile(body);

try {
Response<ResponseBody> response = call.execute();
if (response.isSuccessful()) {
return Result.success();
} else {
return Result.retry();
}
} catch (IOException e) {
e.printStackTrace();
return Result.retry();
}
}
}


👉Новости 👉Платформа
Please open Telegram to view this post
VIEW IN TELEGRAM
#Вакансии
👨‍💻 Android разработчик

Локация: Удалённо
Компания: ООО ИнстаДев
ЗП: от 120 000 до 200 000 р.
Занятость: Полная

🚩Рассматриваем кандидатов с:
▪️Опытом коммерческой разработки на Java/Kotlin;
▪️Опытом применения паттернов: MVP, MVVM, CLEAN;
▪️Опытом работы с внешними библиотеками Dagger2, RxJava2;
▪️Опытом работы с coroutine + flow;
▪️Знанием основных фреймворков, опыт работы с WS/REST/RPC;
▪️Умение писать поддерживаемый, изолированный и тестируемый код;
▪️Желательно знание dagger hilt и jetpack navigation.

🚩Будет плюсом:
➕Знание основных структур данных и паттернов, умение с ними работать;
➕Понимание принципов многопоточного программирования;
➕Опыт создания кастомных UI компонентов;
➕Наличие опыта работы с jetpack(ViewModel, lifecycle, room, paging...).

🚩Мы готовы предложить:
▪️Работу в самом удобном месте - дома или на море под пальмами;
▪️Минимум бюрократии и живое и личное отношение;
▪️Гибкий рабочий график;
▪️Возможность делиться экспертностью с нашими сотрудниками, а также с теми, кто только начинает свой путь в IT;
▪️Оплату обучения;
▪️Большие возможности для развития;
З/п зависит от вашего грейда и обсуждается на собеседовании.

📩 Резюме отправлять: a.borodulina@instadev.net

👉Новости 👉Платформа
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔 Что такое руты в сборщике мусора?

Руты (GC Roots) — это объекты, которые сборщик мусора считает "живыми" и от которых начинается поиск достижимых объектов. Примеры GC Roots:
🟠Локальные переменные в стеке потока.
🟠Статические поля классов.
🟠Объекты, на которые ссылаются JNI (Native) ссылки.
Если объект не достижим из GC Roots, он помечается для удаления.

👉Новости 👉Платформа
Please open Telegram to view this post
VIEW IN TELEGRAM
#ЧеКак
🤔 Что такое мульти-декларации (destructuring declarations)?

Мульти-декларации — это способ извлечения значений из объекта и присвоения их сразу нескольким переменным. В Kotlin этот механизм поддерживается с помощью оператора распаковки (destructuring operator) — componentN(), где N — номер компонента.

🟠При создании data класса Kotlin автоматически создает функции componentN() для каждого свойства класса, где N — номер позиции переменной в конструкторе. Функции componentN() возвращают значения свойств в порядке их объявления в конструкторе. Это позволяет использовать мульти-декларации для распаковки значений свойств и присваивания их отдельным переменным.

🚩Пример
если у нас есть data класс Person с двумя свойствами name и age, мы можем использовать мульти-декларации, чтобы извлечь эти свойства и присвоить их двум переменным:

data class Person(val name: String, val age: Int)

val person = Person("Alice", 29)
val (name, age) = person

println(name) // Alice
println(age) // 29

Также можно использовать мульти-декларации в циклах, чтобы итерироваться по спискам объектов и распаковывать значения свойств:


val people = listOf(Person("Alice", 30), Person("Bob", 40))
for ((name, age) in people) {
println("$name is $age years old")
}

// Alice is 30 years old
// Bob is 40 years old


Мульти-декларации также могут быть использованы с массивами и другими коллекциями:

val list = listOf("apple", "banana", "orange")
val (first, second, third) = list

println(first) // apple
println(second) // banana
println(third) // orange


👉Новости 👉Платформа
Please open Telegram to view this post
VIEW IN TELEGRAM
#ЧеКак
🤔 Разница между merge и rebase

Merge и Rebase — это команды в Git для объединения веток, но работают они по-разному. Merge создает новый коммит слияния, сохраняя историю обеих веток, что может привести к разветвленной истории. Rebase переписывает историю, перенося коммиты текущей ветки на вершину другой, делая историю линейной и более чистой, но с потенциальными рисками для уже опубликованного кода.

👉Новости 👉Платформа
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔 В Kotlin, как можно инициализировать переменную типа List<Int> с числами от 1 до 10?
Anonymous Quiz
20%
val numbers = List(10) { it + 1 }
50%
val numbers = listOf(1..10)
20%
val numbers = (1..10).toArray()
10%
val numbers = mutableListOf(1 until 11)
#ЧеКак
🤔 Можно ли создать data class без свойства (пустой)?

Нет, data class требует хотя бы одного свойства в первичном конструкторе. Это необходимо для автоматической генерации методов equals, hashCode и toString.

👉Новости 👉Платформа
Please open Telegram to view this post
VIEW IN TELEGRAM
#ЧеКак
🤔 В чем преимущества выбора Android разработки?

Выбор Android-разработки предоставляет целый ряд преимуществ, как для разработчиков, так и для бизнеса.

🟠Огромная пользовательская база
Является самой популярной мобильной операционной системой в мире, что обеспечивает доступ к широкой аудитории. Приложения могут достичь значительного числа пользователей по всему миру, увеличивая потенциальные рыночные возможности.

🟠Гибкость и открытость платформы
Предоставляет больше гибкости в плане настройки приложений и интеграции с операционной системой. Это открытая платформа, что позволяет экспериментировать и внедрять новшества с меньшим количеством ограничений по сравнению с другими операционными системами.

🟠Удобство разработки
Предоставляют разработчикам мощные инструменты для создания, тестирования и отладки приложений. Kotlin, который стал основным для Android-разработки, предлагает современные возможности и улучшает производительность и читаемость кода по сравнению с Java.

🟠Поддержка многочисленных устройств
Работает на множестве устройств с различными размерами экрана и характеристиками, что дает возможность охватить более широкий спектр рынка. Однако это также создает вызовы, связанные с адаптацией приложений под разные устройства.

🟠Интеграция с Google Services
Тесно интегрирован с Google Services, такими как Google Drive, Google Maps и другими. Это предоставляет легкий доступ к мощным инструментам и API, которые могут значительно расширить функциональность приложений.

🟠Разнообразие распространения и монетизации
Приложения можно распространять не только через Google Play Market. Существуют альтернативные магазины приложений и платформы, что предоставляет больше вариантов монетизации и распространения своих продуктов.

🟠Сообщество и поддержка
Имеет одно из самых больших сообществ разработчиков, что означает обширную поддержку, большое количество ресурсов, форумов, блогов и документации, которые могут помочь новым и опытным разработчикам.

👉Новости 👉Платформа
Please open Telegram to view this post
VIEW IN TELEGRAM
#ЧеКак
🤔 Сколько типов инстансов у Nothing?

Nothingне имеет инстансов. Это тип, который обозначает, что значение никогда не будет возвращено (например, функция завершает выполнение с исключением).

👉Новости 👉Платформа
Please open Telegram to view this post
VIEW IN TELEGRAM
#Вакансии
👨‍💻 Android developer (Middle+/ Senior)

Локация: Удаленно (команда в Польше и РБ)
Компания: ArtpolDev
ЗП: от 1 500 до 2 500 $
Занятость: Полная

Оформление: ИП, официально, инкубатор

Мы запускаем мобильный проект в сфере Parental Control (конкуренты Kids360, Kidslox). Наша цель — создать продукт, который сделает жизнь родителей проще, а детей — безопаснее. Ищем талантливого Android-разработчика, который станет ключевой частью нашей команды и будет отвечать за полный цикл разработки приложения, включая настройку Firebase для работы с бэкендом.

🚩Что для нас важно в первую очередь
🔵Опыт разработки приложений с нуля до релиза: выбор и настройка архитектуры, интеграция модулей, работа с Firebase (аутентификация, уведомления, хранение данных, аналитика), создание экранов и релиз приложения в Google Play.

🚩Ожидания
🔵 Опыт разработки на Kotlin (Java приветствуется), Jetpack Compose, LiveData/Flow, Room/SQLite.
🔵 Знание архитектурных паттернов (MVVM, MVP, Clean Architecture).
🔵 Уверенная работа с Firebase (аутентификация, уведомления, хранение данных).
🔵 Интеграция сторонних сервисов и API (Adapty, Appsflyer).
🔵 Опыт создания пейволов и проведения A/B тестов для улучшения UX и монетизации.
🔵 Понимание принципов безопасной разработки и защиты данных пользователей.
🔵 Умение работать с ивентами и настраивать аналитику (Amplitude).
🔵 Опыт публикации в Google Play, работа с реджектами.
🔵 Поддержка приложения на различных версиях Android.

🚩Будет плюсом
- Опыт работы с Accessibility API или инструментами для контроля использования устройства.
- Навыки работы и настройки CI/CD.

❗️Скидывайте ссылки на приложения в Google Play, которые вы делали с нуля, и ваше резюме.

​​​​​​​​​​​​​💬 Резюме отправлять: @illarionov_egor

👉Новости 👉Платформа
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
🤔 Как в Kotlin обозначить, что функция принимает другую функцию в качестве параметра?
Anonymous Quiz
45%
(Int) -> String
27%
Function<Int, String>
27%
{ Int -> String }
0%
Callable<Int, String>
#ЧеКак
🤔 Как передать данные с одной Activity на другую?

В Android передача данных между Activity осуществляется через механизм Intent. Intent — это объект, который позволяет передавать данные и запускать компоненты, такие как Activity, Service и BroadcastReceiver.

🚩Передача данных с одной Activity на другую

🟠Передача данных через Intent
1⃣Создание Intent и добавление данных
В первой Activity создайте Intent и добавьте данные, которые хотите передать, используя методы putExtra.
// MainActivity.java
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
intent.putExtra("key", "value"); // передаем строку
intent.putExtra("number", 123); // передаем целое число
startActivity(intent);


2⃣Получение данных во второй Activity
Во второй Activity получите Intent, который запустил эту Activity, и извлеките данные из него.
// SecondActivity.java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);

// Получение Intent и извлечение данных
Intent intent = getIntent();
String value = intent.getStringExtra("key");
int number = intent.getIntExtra("number", 0); // 0 - значение по умолчанию

// Использование полученных данных
TextView textView = findViewById(R.id.textView);
textView.setText("String: " + value + ", Number: " + number);
}


🟠Передача объектов (Parcelable)
Если вам нужно передать сложные объекты, вы можете использовать интерфейс Parcelable. Этот интерфейс позволяет сериализовать объекты для передачи через Intent.

1⃣Создание класса, реализующего Parcelable
import android.os.Parcel;
import android.os.Parcelable;

public class User implements Parcelable {
private String name;
private int age;

public User(String name, int age) {
this.name = name;
this.age = age;
}

protected User(Parcel in) {
name = in.readString();
age = in.readInt();
}

public static final Creator<User> CREATOR = new Creator<User>() {
@Override
public User createFromParcel(Parcel in) {
return new User(in);
}

@Override
public User[] newArray(int size) {
return new User[size];
}
};

@Override
public int describeContents() {
return 0;
}

@Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeString(name);
parcel.writeInt(age);
}

// Getters and setters (если нужны)
}


2⃣Передача объекта через Intent
// MainActivity.java
User user = new User("John", 30);
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
intent.putExtra("user", user);
startActivity(intent);


3⃣Получение объекта во второй Activity
// SecondActivity.java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);

Intent intent = getIntent();
User user = intent.getParcelableExtra("user");

// Использование полученного объекта
if (user != null) {
TextView textView = findViewById(R.id.textView);
textView.setText("Name: " + user.getName() + ", Age: " + user.getAge());
}
}


👉Новости 👉Платформа
Please open Telegram to view this post
VIEW IN TELEGRAM
#ЧеКак
🤔 Как происходит составление хешмапы, если совпадает хеш-код?

Если два ключа имеют одинаковый хеш-код (коллизия), используются механизмы разрешения:
🟠Связанные списки (chaining): элементы с одинаковым хешем помещаются в один bucket в виде связанного списка.
🟠Сбалансированные деревья: современные реализации (например, в Java) используют деревья вместо списков для ускорения поиска при большом количестве коллизий.
🟠Метод equals используется для проверки уникальности ключей в случае совпадения хеша.

👉Новости 👉Платформа
Please open Telegram to view this post
VIEW IN TELEGRAM
#ЛитКод
🤔 Задача: 672. Bulb Switcher II

Есть комната с n лампочками, пронумерованными от 1 до n, которые изначально все включены, и четыре кнопки на стене. Каждая из четырех кнопок имеет разную функциональность:

Кнопка 1: Переключает состояние всех лампочек.
Кнопка 2: Переключает состояние всех лампочек с четными номерами (т.е. 2, 4, ...).
Кнопка 3: Переключает состояние всех лампочек с нечетными номерами (т.е. 1, 3, ...).
Кнопка 4: Переключает состояние всех лампочек с номером j = 3k + 1, где k = 0, 1, 2, ... (т.е. 1, 4, 7, 10, ...).
Необходимо сделать ровно presses нажатий кнопок. Для каждого нажатия можно выбрать любую из четырех кнопок для нажатия.

Даны два целых числа n и presses, вернуть количество различных возможных состояний после выполнения всех presses нажатий кнопок.

Пример:
Input: n = 1, presses = 1
Output: 2
Explanation: Status can be:
- [off] by pressing button 1
- [on] by pressing button 2


👨‍💻 Алгоритм:

1⃣Рассчитаем возможные множества остатков: то есть какие множества c_i = f_i (mod 2) возможны.

2⃣Так как c_i ≡ f_i и c_i ≤ f_i, если ∑f_i ≠ ∑c_i, или если ∑f_i < ∑c_i, это невозможно. В противном случае это возможно простым построением: выполните операции, указанные c_i, затем выполните операцию номер 1 с четным числом оставшихся операций.

3⃣Для каждого возможного множества остатков симулируем и запоминаем, как будут выглядеть первые 6 лампочек, сохраняя это в структуре Set. В конце возвращаем размер этого множества.

😎 Решение:
class Solution {
fun flipLights(n: Int, m: Int): Int {
val seen = mutableSetOf<Int>()
val n = minOf(n, 6)
val shift = maxOf(0, 6 - n)
for (cand in 0 until 16) {
val bcount = Integer.bitCount(cand)
if (bcount % 2 == m % 2 && bcount <= m) {
var lights = 0
if ((cand shr 0 and 1) > 0) lights = lights xor (0b111111 shr shift)
if ((cand shr 1 and 1) > 0) lights = lights xor (0b010101 shr shift)
if ((cand shr 2 and 1) > 0) lights = lights xor (0b101010 shr shift)
if ((cand shr 3 and 1) > 0) lights = lights xor (0b100100 shr shift)
seen.add(lights)
}
}
return seen.size
}
}


👉Новости 👉Платформа
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔 В Kotlin, как обозначить функцию, которая принимает переменное количество аргументов одного типа?
Anonymous Quiz
67%
Использовать vararg
22%
Использовать array
11%
Использовать list
0%
Использовать spread