Руководство по React Native для начинающих Android-разработчиков (с примером приложения)
Представляем вам перевод статьи Nikhil Sachdeva, опубликованной на hackernoon.com. Автор делится опытом разработки мобильных приложений с помощью React Native и предлагает создать свое приложение, используя этот фреймворк.
Я был Android-разработчиком и довольно длительное время использовал в работе Java. Лишь недавно я попробовал свои силы в создании мобильных приложений с помощью React Native. Это заставило меня взглянуть на процесс разработки по-новому, если не сказать больше. Цель моей статьи — показать, какие различия я заметил, используя эти два фреймворка в разработке приложений.
Что такое React Native
«React Native позволяет создавать мобильные приложения, используя при этом только JavaScript с такой же структурой, что и у React. Это дает возможность составлять многофункциональный мобильный UI с применением декларативных компонентов».
«Приложения, которые вы создаете с помощью React Native, не являются мобильными веб-приложениями, потому что React Native использует те же компоненты, что и обычные приложения для iOS и Android. Вместо того чтобы использовать язык Swift, Kotlin или Java, вы собираете эти компоненты с помощью JavaScript и React».
Итак, получается, что React Native — это фреймворк, в основе которого лежит React.js, что позволяет разрабатывать кроссплатформенные приложения как для Android, так и для iOS.
Вы спросите, зачем уходить от привычного Java и осваивать JavaScript и React.js? Вот несколько плюсов использования этих языков.
Плюсы: в чем вы выиграете
1. Кроссплатформенная разработка
Основная цель разработчиков — предоставить клиентам сервисы. Никто не хотел бы, чтобы его пользователи были ограничены лишь одной какой-то платформой только потому, что разработчик не может создавать приложения для других платформ. Следовательно, и сам разработчик не должен ограничивать свои способности только потому, что ему или ей комфортно работать с конкретным инструментом разработки.
Фреймворк React Native является портативным, то есть его единая кодовая база, написанная в JavaScript, создаст модули как для Android, так и для iOS.
2. Освоение React
Освоив React Native и JavaScript, вы откроете для себя новый мир front-end разработки применительно, например, к веб-сайтам. Фреймворк React Native основан на тех же компонентах, что и React, поэтому полученные здесь навыки не ограничиваются только разработкой мобильных приложений.
3. Время сборки быстрее, чем в Android Studio
Вы когда-нибудь тратили больше 2–3 минут на сборку, чтобы протестировать/пофиксить базовую функцию, и при этом багфикс растягивался на долгие часы? Решением проблемы станет React Native. С ним на сборку уходит значительно меньше времени. С такой функцией, как «Горячая перезагрузка» (Hot Reloading), разработка и тестирование пользовательского интерфейса — это легко. Благодаря этой функции приложение перезагружается каждый раз, когда JS-файл сохраняется!
4. JavaScript удобен для передачи данных по сети
В React Native вызов API, рендеринг изображений по URL и другие процессы очень просты. Больше не нужно использовать Retrofit, OkHttp, Picasso и т. д. Намного меньше времени тратится на настройку. Когда данные поступают из API на платформе Android, они сначала преобразуются в POJO-модель и лишь затем используются в элементах UI. А вот данные JSON, полученные в React Native, удобны для JavaScript и могут напрямую использоваться для предпросмотра UI. Это позволяет облегчить веб-интерфейс для GET или POST-запросов от REST API.
5. Разработка UI
В React Native в качестве разметки UI выступает модуль flexbox, серьезный конкурент XML-разметки на Android. Flexbox очень популярен в сообществе веб-разработчиков. В React Native UI-элементы в основном должны разрабатываться с нуля, тогда как в нативной разработке для Android библиотека поддержки Google Design Support Library уже подключена. Это дает разработчику свободу в плане интерактивного и адаптивного дизайна.
Минусы: в чем вы, быть может, проиграете
1. Возможно, вы ненавидите JavaScript
Многие люди не любят JavaScript просто за то, что этот язык не похож на традиционные языки, такие как Java, C++ и другие. Подробные негативные отзывы вы можете найти здесь и здесь.
2. Не так уж много сторонних библиотек
Сообщество React Native по-прежнему находится в стадии становления и поддерживает сторонние библиотеки, не такие популярные, как нативная библиотека Android (кстати, оцените слайд-шоу моей библиотеки для Android ).
Пример приложения
Для начала давайте попробуем разработать приложение для извлечения данных из API, чтобы понять, насколько просто работает React Native. Очевидно, что первым шагом является установка React Native. Для этого перейдите на официальный сайт. Также вы найдете там замечательную инструкцию для начинающих — прочтите ее. Мы будем использовать фиктивный API https://jsonplaceholder.typicode.com/photos, который содержит следующие данные:
Обратите внимание, что для Android работа с API с использованием таких библиотек, как Retrofit/OkHttp, — это сложная задача. Однако мы видим, что динамический и итеративный язык JavaScript упрощает эту работу.
Перейдем к созданию проекта MockApp:
react-native init MockApp
cd MockApp
Далее запустите его на вашем виртуальном/локальном устройстве, используя:
На экране появится такое изображение:
Стартовый экран приложения
Приложение для работы с API, которое мы создадим, будет выглядеть вот так:
Так в результате выглядит приложение
Теперь откройте проект в текстовом редакторе и скорректируйте App.js, как показано ниже:
В этом коде довольно много информации. Я дам краткий обзор по всем основным ключевым словам в коде, но продолжайте поиск по каждому ключевому слову, которое вам непонятно. Это займет некоторое время.
1. componentDidMount. Это часть React Native в жизненном цикле приложения. componentDidMount() запускается сразу после того, как компонент был добавлен в дерево компонентов.
2. fetch. Чтобы работать с сетевыми запросами, в React Native существует API-интерфейс Fetch.
3. Переменные состояния (isLoading, dataSource). isLoading — это переменная типа bool, которая показывает, загружены данные API или нет. dataSource — переменная, которая сохраняет ответ JSON от команды fetch.
4. FlatList. Это эквивалент RecyclerView в React Native, только намного проще. Компонент FlatList отображает скролящийся лист данных, которые могут изменятся, хотя и имеют общую структуру. FlatList отлично подходит для работы с длинными списками, в которых количество элементов может меняться с течением времени.
Как мы видим, в списке данных нам не нужно отделять переменные для каждого элемента. В этом и заключается красота динамического языка, то есть языка JavaScript. Тип переменной определяется в реальном времени, поэтому работа даже с большими объемами данных остается простой задачей.
Как мы видим, стили каждого компонента уже определены. Нам нужно задать значения переменных. Это можно сделать следующим способом:
На этом наша работа заканчивается. Нам удалось создать приложение, компоненты которого могут предварительно просматриваться благодаря использованию API.
React Native — одного JS мало
Итак, пришла пора быстро погрузиться в тему. Для усиления эффекта, использую разные техники преобразования информации в знания. В частности, представляю конспект доклада Алексея Андросова (старшего разработчика интерфейсов, Yandex).
React Native — это фреймворк для разработки кроссплатформенных приложений для iOS и Android:
Первый ли он? Нет!
Инструменты разработчика
React Native: взгляд сверху
React Native: взгляд изнутри
Write once, run everywhere? Нет! Вместо ожидаемых предположений, что один и тот же код будем использовать многократно на разных платформах. Learn once, write everywhere. Одинаковая архитектура приложения (React для построения интерфейса, Redux для круговорота данных).
Немного философии
Все нативно, поэтому забудьте про полную кроссплатформенность. Платформы разные, поэтому и компоненты разные. У них разная логика и механика взаимодействия. Можно писать все на JS и выкинуть понятие native, но вы этого не хотите. Native — это ваше преимущество!
На примере приложения Vine в iOS. Что принято делать в iOS? Внизу TabBar, в нем принято переключать экраны: главная, профиль, поиск. Сверху NavigationBar, и в нем принято писать название и кнопки слева-справа (слева обычно back стоит, а справа — какое-нибудь действие). А в Android все не так. Есть тоже NavigationBar, но он другой, в нем не принято кнопки делать. Для этого есть отдельный компонент, называется ToolBar-ом. В Android-е принято делать SegmentedActivity — она сверху, очень похожа на iOS TabBar, но механика работы у него абсолютно другая. Если в TabBar-е мы не можем свайпом переключать экраны, то в Android-е это можно делать, и это принято делать, и именно так оно и работает.
Кроссплатформенность
Из чего состоит приложение?
Компоненты
Приложение строится из компонент платформы — это нативные модули, завернутые в React-компоненты
[Вот так это выглядит, реальный код]
Интересно, что кнопок нет! Для вас любая кнопка — это просто стилизованная область, у которой есть обработчик нажатия. Никакой механики кнопки нет. И поэтому в React-е есть вот эти touchable-элементы, вы оборачиваете всё, что угодно и у вас всё что угодно становится кнопкой по сути (есть обработчик onPress). Scroll-ы — отдельный компонент. Это сегментированный вид. Он рендерит только то, что находится на экране, и с ним нужно работать чуть по другому. Потому ScrollView тут тоже отдельный. Отдельная механика, если используется клавиатура. Потому отдельное свойство есть — чего с ним делать. Отдельно свойство refreshControl. Если кто-то знает, как разрабатывать на iOS, то это очень похоже.
[Вот как выглядит текстовое поле]
Какие-то свойства совпадают с привычным HTML-input-ом, а другие — нет.
CSS не настоящий — это полифил
Компонент PixelRatio преобразует значения из density points в настоящие пиксели для разных экранов (Retina и прочее).
Вот это пример с flex-ом. Хватает минимального набора, чтобы верстать.
Болванка приложения
[Пример кода приложения]
Navigator
Во многом, проблемы решаются с помощью redux.
Чтобы запушить какой-нибудь роут, или сделать back (перемотать на другой экран) — надо сделать ссылку на Navigator, а потом эту ссылку получить. Причем изначально её не будет, т.к. Navigator-а еще нету.
[Интерфейс выглядит, как связанные компоненты]
[А на самом деле всё выглядит вот так]
NavigationBar или зачем нужен redux
В декабре 2015 Eric Vicenti организовал проект navigation-rfc, с помощью сообщества, попытался решить проблемы Navigator. В феврале 2016 проект переехал в мастер React Native под название NavigationExperimental и теперь развивается силами Facebook. А старый Navigation больше не будет поддерживаться.
NavigationExperimental — что сделано
[Пример кода навигации]
Анимации
[Пример кода анимации]
Работает очень плавно, можно комбинировать последовательно/параллельно, и делать довольно безумные штуки.
Нативные модули
React Native реализует основные, но не все. Если модуля нет:
Как подключить нативные модули
Используйте rnpm — React Native package manager:
Кроссплатформенность компонент
Неправильный путь — разложить все по папкам:
и подключать их в зависимости от платформы
Правильный путь — разложить все по папкам:
Для платформо-зависимых компонент (ComponentIOS, ComponentAndroid) удобно класть рядом пустышку, и не испытывать проблем, что какой-то компонент не найден на платформе.
Как написать нативный компонент
Коллега скинул ссылочку на Weex — две недели назад Alibaba передал проект Apache.
И опять внутри Vue. Что-то оно все время путается у меня под ногами.
Только проникся идеями React+Redux, бегаю с ними, как сумасшедший с бензопилой, в попытках везде применить. А тут что получается — разворачивай дебаркадер?!
Будет очень интересно почитать сравнение, может кто возьмется — тема на Хабре новая.
React Native — применение и критика
Чаще всего при выборе этого языка ожидается, что разработка одного приложения под две платформы займёт в два раза меньше времени, чем разработка двух приложений. Но по итогу оказывается, что разработка занимает столько же, если не больше, из-за сложностей, скрытых под внешним блеском и маркетингом. Мы расскажем о некоторых подобных сложностях, с которыми нам пришлось столкнуться за последние несколько месяцев работы с React Native.
React Native адаптирует Javascript под разработку для мобильных устройств. Это достигается тем, что для сборки проектов он использует несколько сборщиков — Metro Bundler, который интерпретирует JS-код и представляет ресурсы и сборщик целевой системы. В нашем случае это был gradle для Аndroid. В теории приложение React Native должно запускаться довольно просто. Команда react-native run-android включает Metro Bundler и выполняет сборку приложения для всех подключенных Android-устройств и эмуляторов.
В реальности оказалось, что даже на этом этапе есть сложности. На нашем проекте постоянно возникала ошибка «Unable to download JS bundle», которая означала, что bundler не может транслировать код в нативный. Как позже выяснилось — из-за того, что он не запустился. StackOverflow подтвердил догадки и подсказал, что стоит запускать bundler отдельным потоком с помощью команды react-native start. Это позволяет перезапускать bundler только если поменялся package.json, потому процедура не сильно замедляет разработку.
Из-за того, что все библиотеки пишутся в разное время, они используют разные версии SDK и требуют разного подхода. Иногда бывает так, что библиотеки несовместимы друг с другом, или последняя версия библиотеки оказывается экспериментальной, и сами разработчики советуют понизить версию до предпоследней. Довольно часто link не настраивает все требуемые зависимости. Так, для вышеупомянутого firebase требуется добавить множество дополнительных библиотек в нативном коде, подключить различные внешние репозитории, модифицировать mainApplication.java (и это только для android!). Для Firebase есть достаточно понятная инструкция по выполнению этих действий, но для других библиотек она присутствует не всегда.
После того, как связи с нативным кодом настроены, можно собирать проект в надежде, что подключенная библиотека заработает. При сборке стоит помнить, что если вы получаете ошибку, то стоит удостовериться, что она возникла именно из-за ваших действий, а не из-за ошибки сборщика. Для полной уверенности стоит выполнить следующую последовательность действий:
Данная команда удалит папку node_modules, а затем загрузит её заново. Это одна из самых долгих задач, потому стоит использовать её крайне редко. На некоторых проектах node_modules может занимать до нескольких гигабайт на жестком диске, а потому переустановка займёт время.
В ходе разработки было замечено, что часто неудачный билд — следствие того, что сборщик не может создать (или удалить) папку из директории debug. Данное действие решает проблему того, что react не может самостоятельно удалить папку. Но в то же время генерация файлов для этой папки с нуля опять же займёт дополнительное время.
Запустить Metro Bundler. Эта вкладка должна оставаться открытой на протяжении всего процесса отладки. Если случилась ошибка, то лог ошибки может появиться здесь. Скорее всего при ошибке этот процесс завершится, и его снова нужно будет перезапустить.
Установить приложение на подключенное устройство или эмулятор. Большинство ошибок сборки случаются именно здесь, и часть из них понятна, но часть довольно иррациональна и «лечится» перезапуском всего процесса.
Представим процесс сборки последовательностью команд для одного проекта (уже имеющего realm, redux, react-navigation, ещё около десяти библиотек) после подключения Firebase.
Стоит ли говорить, что это занимает действительно много времени? И это не единоразовый процесс: к описываемому моменту эта процедура требовалась почти после каждого изменения в коде программы. С каждой новой библиотекой проект становится всё менее стабильным, и данный процесс может меняться, чаще всего в худшую сторону. Отладка приложения — это одна из важнейших функций для разработчика, а в данном случае её скорость довольно сильно уменьшается.
Кстати об отладке. Отладчик React Native имеет проблемы не только с запуском. Исправление ошибок, найденных вследствие теста, тоже довольно болезненный процесс. В react-native JS-код транслируется в Native-код, но в процессе трансляции обфусцируется. Так что если не хотите видеть ошибки типа «null pointer exception in zzz.yyy()», то нужно пользоваться встроенным отладчиком, не получится просто читать exception’ы в logcat. При ошибке отладчик показывает красный «экран смерти» с её описанием, более-менее подталкивающим в сторону пути исправления. Но и с этой частью есть проблемы.
Хорошо, когда ошибка выглядит так:
Здесь действительно понятно, что происходит — вместо ожидаемого объекта массива в переменной this.state.noteArray.map находится undefined, из-за чего возникает пресловутая TypeError. Исправить её можно переходом на app.js:14 и проверкой значения в данной переменной перед использованием.
Хуже, когда ошибка выглядит так:
Изображения взяты из интернета, но мы видели их и «вживую». И несмотря на то, что они показываются в runtime, эта ошибка не связана с тем, что что-то было сделано неверно именно в вашем коде. Это может быть следствием того, что вы неверно установили библиотеку, или если в ваших импортах есть несовместимые зависимости, или что-то пошло не так в native-коде, а ошибку пытается отловить React. Каждая ошибка индивидуальна и решается крайне по-разному. Хорошо, что существует StackOverflow и хоть какой-то режим отладки.
Еще хуже, когда ошибка не воспроизводится в debug. С данной ситуацией мы столкнулись при попытке собрать приложение с новой версией React с поддержкой x64-архитектур для Android. При установке приложения с дебаггером всё работает отлично. Но как только мы делаем сборку тестеру на телефон, всё прекращает работать и ломается как только доходит до взаимодействия с базой данных. Чтобы отладить неотлаживаемое на скорую руку используем консольные сообщения, в роли которых в данном случае выступал компонент react toastAndroid. Этот компонент выводит на экран короткий текст по достижению определенной строчки кода. Методично, желательно деля код пополам, локализуем функцию, в которой происходит ошибка, и выясняем, что метод Object.assign(<>, item) не работает в новой версии React. Повезло, что можно было заменить эту функцию на более короткую <. item>при сохранении функционала приложения, но поиск этой ошибки обошелся в примерно десяток часов работы.
После было проведено небольшое исследование в поисках причин. Как обнаружилось, для интерпретации JS-кода в debug и production версиях React Native использует разные Javascript-движки: для отладки Chrome JS engine, а в работе JavaScriptCore. Да, React Native не переводит JavaScript в нативный код, а интерпретирует по ходу выполнения. При этом отладочный движок работает куда стабильнее, а потому баги всё чаще прокрадываются в production. К примеру, в этой статье показано, как форматирование даты работает в разных условиях. Возвращаясь к ошибке: так вышло, что после обновления версии React Native веб-движок production-версии потерял поддержку Object.assign(). А отладочный движок остался тот же.
Пожалуй, худший вариант — это случай, когда приложение ломается в случайных местах, только в production-версии и без каких-либо логов со стороны React Native. Пример: после установки релизной версии приложения на телефон оно «работает какое-то время», а потом «выключается без ошибки или предупреждения в случайный момент». Причём ошибка воспроизводится не на всех устройствах. В конце концов, методом проб и ошибок (и обнаружением того, что вышеупомянутый Firebase Crashlytics не присылает соответствующих ошибок) удалось выловить логи падения, которые выглядели так:
Этот текст даже не относится к нашему приложению, он даже не был отмечен красным. Но после того, как мы его получили и отправились на форумы, мы обнаружили, что новая версия React Native сломана. И предыдущая была сломана. На официальном Issue Tracker ошибка «Android crashes: signal 11 (SIGSEGV)» существовала уже два месяца, и к нашей удаче за два дня до того, как мы обратился туда (!) было предложено экспериментальное решение, которое исправило ошибку.
Иронично, что некоторые разработчики, которым приходилось сталкиваться с Android Studio, были в недоумении по поводу того, что в IDE есть такие опции как build/clean project или file/invalidate caches. Это требуется для того, чтобы избавиться от аномального поведения gradle, от ложных сообщений об ошибках и предупреждениях, от ошибок синхронизации. Разработчики спрашивали: «почему мы должны делать работу за нашу IDE, в таких ситуациях эти команды должны выполняться автоматически». И их можно понять, но в то же время современные IDE и так делают всю сложную работу за кадром. А эти разработчики попросту не работали с React Native.
Всё рассказанное — это единичные случаи, случившиеся за последние несколько недель. Здесь мы не описываем сложности запуска приложений с Expo, с настройкой стиля кода в babel/eslint, не ругаем Javascript за излишнюю гибкость, не рассказываем как на одном из проектов почти полностью пропала возможность отладки из-за связки redux/realm. Учитывая описанные сложности поддержки и разработки и тот факт, что для двух систем это всё умножается на два — стоит задуматься, действительно ли React Native выгоден? После того как мы завершили наш третий проект на этом языке, мы решили, что нет. Как вы считаете?
Как разработать своё первое приложение на React Native
Авторизуйтесь
Как разработать своё первое приложение на React Native
технический директор Secreate
Привет я Никита, занимаюсь разработкой на React/React Native и на всяких других штуках в Secreate. Хочу немного поговорить о том, что же всё-таки такое React Native, почему он сейчас важен и популярен, а также вместе с вами попробую написать небольшой проект для демонстрации основ.
Что такое React Native?
Сначала нужно разобраться, что есть React. React — это инструмент для создания пользовательских интерфейсов. Его основная задача — обеспечить отображение на экране того, что можно увидеть на веб-страницах. React позволяет легко создавать интерфейсы, разделяя каждую страницу на небольшие фрагменты и компоненты. Он очень удобен для создания веб-приложений и не требует большого порога вхождения. Так вот, ребята из Facebook подумали, что было бы круто, если бы React можно было бы использовать для создания кросс-платформенных мобильных приложений, и в 2015 году React Native был представлен публике и появился на GitHub, где уже каждый мог внести свой вклад. React популярен по нескольким причинам. Он компактен и отличается высокой производительностью, в особенности при работе с быстро меняющимися данными. За счет своей компонентной структуры, React поощряет вас писать модульный и многократно используемый код.
В мире кроссплатформенной мобильной разработки уже были свои решения, к примеру Apache Cordova — технология, которая позволяла использовать HTML + CSS + JavaScript + нативный функционал платформы, на которой приложение было запущено, для его работы. Однако, технология имеет большую проблему — быстродействие. Так же на данный момент существуют и другие, такие как Xamarin, Flutter, QT и так далее.
В React Native код пишется на JavaScript, и исполняется при помощи JavaScriptCore — движка, который использует Safari. Так же можно использовать нативные модули платформы, к примеру камеру или Bluetooth. Для этого пишется код, реализующий функциональность на языке, который предназначается для разработки под конкретную платформу (Java/Swift/Objective C) и сообщается со средой JavaScript посредством bridge.
Если сравнивать с типовой разработкой для iOS и Android, React Native предлагает много других возможностей. Так как ваше приложение в основном состоит из JavaScript, можно воспользоваться многими преимуществами. Например, для того чтобы увидеть добавленные в код изменения, вы можете немедленно «обновить» приложение, не дожидаясь завершения билда.
Для большинства стандартных элементов UI есть компоненты в RN, к примеру View = UIView в iOS, так что реализовывать изыски интерфейса должно быть несложно, если есть знания React.
Почему же RN стал таким популярным?
Первое приложение
Давайте попробуем написать своё первое приложение и понять что для этого нужно. Пусть это будет, к примеру, приложение для отображения и поиска разных пользователей.
Нам понадобится cli утилита npx, которая поставляется вместе с Node.js, Android Studio — если мы хотим протестировать приложение на Android, либо Xcode — если на iPhone. Как установить указанные инструменты подробнее можно почитать здесь.
Спустя какое-то время у нас создалась такая структура папок
В index.js написано:
import
Начнем с создания роутера. В браузере, когда пользователь кликает по ссылке, URL добавляется в стек истории переходов, а когда он жмет кнопку назад — браузер удаляет последний посещенный адрес из стека. В RN по умолчанию такого понятия нет, для этого и нужен React Navigation. В приложении может быть несколько стеков. К примеру у каждого таба внутри приложения может быть собственная история посещений, но может быть и один.
Что здесь происходит? Создаётся новый стек навигации, в котором указывается список экранов, находящихся в нем. А также указывается стартовый экран стека. Т. к. у нас будет всего один стек, то по сути это и будет стартовый экран приложения.
Там разместим такой код:
Сборка и запуск
Когда проект запустится, то на экране должно появиться, что-то вроде этого.
Для отладки приложения можно использовать react-native-debugger, либо браузер. Включается дебаггер комбинацией клавиш ctrl(cmd) + M для Android, cmd + D для iOS. Там же можно включить live reload.
Сверху к import из react-native добавим импорт модуля StyleSheet
Вниз этого же файла добавим
При подтяжке экрана вниз — список обновляется, при скролле — догружается. Добавим возможность перехода в карточку юзера.
Это переход в экран с названием info с передачей выбранного юзера как параметра. В дальнейшем его можно будет получить из компонента экрана. Теперь добавим этот экран в навигатор RootNavigator.js и напишем для него код.
Так же создадим файл src/screens/PersonInfoScreen.js и добавим туда следующий код.
Вот что у нас получилось.
Таким образом мы сделали приложение для вывода и просмотра некоторой информации по разным людям.
Ресурсы
Для изучения RN можно найти много ресурсов, вот небольшой список:
В итоге
React Native — это мощная платформа, используемая предприятиями любого размера для создания мобильных приложений. Это быстрый, эффективный и относительно простой способ для создания приложений на JavaScript. Главным его преимуществом является то, что он позволяет быстро создавать приложение под несколько платформ одновременно, а также имеет невысокий порог вхождения. React Native широко используется крупными брендами, поэтому не стоит беспокоиться о том, что он куда-то денется в ближайшие пару лет.










