Сообщество - Android Developers

Android Developers

90 постов 2 044 подписчика

Популярные теги в сообществе:

Волна по "Честной цене" - тру приложение для Android ч.3

Здорово, пикубушники и пикабушницы.

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

Напомню, давным давно мы заловились с товарищем @Stich.626 чтобы сделать единообразное и бесплатное мобильное приложение + сайт для расчета ценников в магазинах, которое решили не бросать, любить и лелеять, насколько это возможно.

Волна по "Честной цене" - тру приложение для Android ч.3 Цены, Приложение на Android, Программирование, Rustore, Google Play, Длиннопост

0 - Что делаем сегодня?

В данном посте мы добавляем функционал сравнения ценников, смотрим отзывы пикабушников из магазинов приложений, и конечно же внедряем новые удобства на основе этих самых отзывов (иначе зачем мы их читаем). Готовы? Поехали!

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

Если вы просто хотите посмотреть программу, скачать / потыкать ее в действии, или просто посмотреть что это за штука, пожалуйста посмотрите обзорный скриншот выше, или проследуйте по ссылкам, которые я публикую без зазрения совести - потому что само приложение бесплатное, и таковым и останется:

https://play.google.com/store/apps/details?id=ru.oneclickstu...

https://www.rustore.ru/catalog/app/ru.oneclickstudio.fairpri...

1 - Разбираемся с понятием сравнения

Итак, в самом начале давайте поразмышляем, зачем вообще нам может быть полезен такой раздел со сравнением, и обусловлена ли необходимость в нем как такового (потому что у нас уже есть прекрасный список, который хоть чуть чуть, но выполняет эти задачи):

  • Когда мы сравниваем один (или несколько) ценников на товарах, обычно мы смотрим их по схожим характеристикам. Например, мы хотим узнать, какое самое дешевое молоко из представленного в магазине. Или пиво. Или хлеб. Или что вы там вечером едите :)

  • В связи с этим у нас формируется некий "паттерн" поведения пользователя в реальной жизни. Ага, я увидел пельмени по 450 рублей за 500 грамм, теперь я хочу сравнить другие пельмени, и посмотреть, что дешевле в пересчете на килограмм.

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

  • Другими словами, было бы очень удобно "на лету" подсвечивать самое выгодное предложение (каким нибудь зеленым цветом), но при этом ограничить расчеты по одному типу (к сожалению, пельмени не измеряются в литрах, а жаль)

1.1 - Макет, рисуйся!

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

Волна по "Честной цене" - тру приложение для Android ч.3 Цены, Приложение на Android, Программирование, Rustore, Google Play, Длиннопост

На данный момент нам прекрасно подойдет слой с результатами, который мы видим после каждого расчета. Считаю это удобным, так как при необходимости мы начнем сравнивать сразу с этой цены, а еще нам не нужно выбирать тип сравнения (мы его выбрали ранее), а даже если в этом в расчете нет необходимости, можно просто вернуться назад как обычно.

Для этого немного немного поправим данный слой, добавим новую кнопку, и иконки для наглядности, и выделим функцию шеринга (если ей еще кто то пользуется в этом веке). Действия объясняются буквально одной строкой для вьюх типа Button:

android:drawableLeft="@drawable/back_48px"

1.2 Экран активности

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

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

Передаем мы, напомню, сведения из последнего расчета

Волна по "Честной цене" - тру приложение для Android ч.3 Цены, Приложение на Android, Программирование, Rustore, Google Play, Длиннопост

Экран с тестовыми сведениями для наглядности

Что мы можем тут узреть:

  1. Приветственная карточка, которая повторяет функционал из главной формы, и служит напоминанием, что тут вообще происходит. Кстати, считается плохой практикой учить пользователя что делать (программа должна быть сразу интуитивно понятной), но для самых маленьких я не могу не оставить такую подсказку. И конечно, ее можно скрыть, посредством sharedPreferences, и она не будет надоедать.

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

  3. Еще одна карточка для ввода значений, и добавления их к нашему списку. Постарался уместить ее в одну строку для быстроты ввода, при этом не нарушая читабельности (везде ясно что где вводится)

1.3 Принимаем и передаем сведения

Чтобы информация о последнем расчете попала в нашу активность, ее нужно передать из предыдущей. Для этого мы назначаем отдельный метод для кнопки "Начать сравнение", который остается в главной форме:

Intent intent = new Intent(MainActivity.this, CompareActivity.class);
intent.putExtra("get_compare_price", compare_price);
intent.putExtra("get_compare_weight", compare_weight);
intent.putExtra("get_compare_type", compare_type);
intent.putExtra("get_compare_result", compare_result);
startActivity(intent);

А в следующей активности мы уже запрашиваем эти сведения в onCreate, дополнительно убеждаемся в том что запрошенные поля не пустые (чтобы не получить NullPointerException, если приложение будет выгружено из памяти), и помещаем их на форму через метод добавления первого пункта.

get_compare_price = intent.getStringExtra("get_compare_price");
get_compare_weight = intent.getStringExtra("get_compare_weight");
get_compare_type = intent.getStringExtra("get_compare_type");
get_compare_result = intent.getStringExtra("get_compare_result");

Bundle extra = intent.getExtras();
if (extra !=null) {
SetFirstCompareItem();
}

1.4. Возвращаем значения расчетов к изначальному виду

Когда мы передавали результат из одного экрана на другой, то мы поневоле изменили тип передаваемых сведений. Был double при передаче, а стал String.

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

Поэтому мы меняем типы обратно, посредством

Double.parseDouble(имя_переменной)

1.5. Считаем!

Теперь, когда мы готовы к подсчетам, выполняем стандартные действия из предыдущего экрана, ограничивая размер списка 5 элементами.

Предыдущие действия = означает добавление показателей в массив списка как на первом экране, при этом мы сравниваем новый результат со всеми предыдущими, и если он меньше, мы перекрашиваем самый выгодный элемент в зеленый, а остальным назначаем стандартный.

Способ крайне неудобный, но быстрый в написании, и если бы элементов списка было.. ну штук 50, приложение бы офигело, и сожрало всю память вашего устройства.

При этом, обновился тип для формирования цены - раньше он указывался без привязки с региону, и в некоторых местах цена была с запятой (123,45), а где то с точкой (123.45)

Если для простого списка на главной пофиг, что показывать, то для сравнения такое нельзя оставлять, так как приложение сразу вылетит, информируя нас о несопоставимых типах данных, поэтому приведем их к общему знаменателю вообще везде, оставив в качестве разделителя точку, и указав регион:

String.format(Locale.ENGLISH, "%.2f", price) + " ₽"

1.6 Новые удобства

Чтобы считать было еще удобнее, добавим метод, который после каждого добавления по кнопке (или по клавише с клавиатуры) вновь активирует текстовые поля. Вроде мелочь, а необходимости тыкать по новой в графу цены больше не будет:

private void ClearInputs() {
getInputPriceItemCompare = findViewById(R.id.getInputPriceItemCompare);
getInputWeightGRCompare = findViewById(R.id.getInputWeightGRCompare);

getInputPriceItemCompare.setText("");
getInputWeightGRCompare.setText("");

getInputWeightGRCompare.clearFocus();
getInputPriceItemCompare.requestFocus();
}

2. Новые удобства из отзывов

Так как отзывы я читаю (и даже иногда отвечаю), то будем руководствоваться сразу скриншотами. Итак, рассмотрим вопрос, о котором я раньше не думал:

Волна по "Честной цене" - тру приложение для Android ч.3 Цены, Приложение на Android, Программирование, Rustore, Google Play, Длиннопост

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

Чтобы добавить такой способ на нажатие из экранной клавиатуры, воспользуемся объявлением слушателя для наших полей, которые уже есть в форме:

TextInputEditText.OnEditorActionListener

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

К сожалению, устройств (и версий андроида) настолько много, что у одних может показываться галочка (ОК), а у кого то стрелка вперед (NEXT). Чтобы этого избежать, дайте два определим реакцию на обе клавиши:

public boolean onEditorAction (TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_DONE || actionId == EditorInfo.IME_ACTION_NEXT) {
AfterStart();
return true;
}
return false;
}

Тут стоить дать несколько слов о методе AfterStart(), ведь ранее мы использовали другой способ BtnStart(View view)

Как не трудно догадаться, методы сами по себе отличаются, и один унаследован (и объявлен) в слое (View), где мы верстали экран, поэтому вызвать метод, который объявлен в коде мы не можем.

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

Поэтому было решено сделать "костыль" - метод, объявленный через View, вызывает программный метод в коде. Все довольны, добавлено.. ну три строчки кода

3. Что по багам?

3.1 Уже передав версии в релиз, я обнаружил, что часть сведений, которые мы меняли для нового экрана остались в старом формате. Это видно по скриншоту в самом начале:

Волна по "Честной цене" - тру приложение для Android ч.3 Цены, Приложение на Android, Программирование, Rustore, Google Play, Длиннопост

Этот тип данных поступает в формате String, поэтому часть текста будет обрезаться, если число само по себе ровное (без копеек)

А если же наоборот, передать сумму с копейками, то в новом экране покажется правильный формат, но он по все равно не тот, публикуется как String, а должен быть double

Так как эта часть кода не участвует в методе расчета, то ничего не поломается, но внутренний перфекционист недоволен, и я обязательно поправлю в будущем.

3.2 Для экрана сравнения хорошо бы добавить (в заголовке) что мы вообще сравниваем - килограммы, литры, или штуки. Думаю будет полезно, и главное наглядно

3.3. И возможно, стоит удалять элементы из списка, чтобы переписать что нибудь. Об этом я не подумал, но вы напомните в отзывах

И конечно же предлагайте свои варианты, смотрите, оценивайте, считайте.

Спасибо, что дочитали эту портянку текста, спасибо тем, кто оставляет теплые слова, а также тем, кто закидывает на пачку чипсов.

Всем бобра!

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

Теперь точно пока!

Показать полностью 4

Визуальная новелла о Русско-японской войне в стиле... фэнтези

Миноносец Яростный.
Проект начал писать как историческую ролевую текстовую игру, где пользователь выбирая варианты ответов сможет продвигаться по сюжету будучи капитаном одного из кораблей Второго Тихоокеанского флота, выдвигаясь в сторону Порт-Артур для помощи в снятии осады (спойлер: не успели).

А по мере написания игра обрастала новыми идеями, и теперь тут есть ресурсы, которые можно потерять или получить в случайных событиях, есть КНИГИ, да книги, пока две, покупка каждой из которых откроет новую ветку сюжета, отводя игрока от исторических событий к альтернативной истории.

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

Визуальная новелла о Русско-японской войне в стиле... фэнтези Игры, Игры на Android, Русско-японская война, Визуальная новелла, Android разработка, Игровой дизайн, Творчество, Длиннопост

да, одна из книг Некрономикон

В итоге игрок выходит из боя победителем, либо game over и часть накопленных очков игры он сможет использовать при очередной попытке пройти игру (тот самый рогалик). Эта идея еще не реализована, а только на бумаге.

Игра на сегодняшний день совсем не закончена, написана на 15% от начальной задумки. Проект остановился, когда я выходил на финишный этап в своей учебе. Пришлось отоложить, чтобы не провалить учебные проекты. Учебу я недавно закончил и вот зачем пишу сейчас тут на Пикабу - требуется вдохновения писать новые сюжетные арки, местами не хватает опыта правильно собрать проект такого типа.

// скажи что-нибудь на програмистовском: Стек не игровой, вместо unity стандартный набор в андроид студии для приложенек на котлин: MVVM, SingleActivity(+Fragments), Koin, Jetpack Navigation Component и тд. Почему таковы выбор стека? Учеба моя и планы на будущее связаны с продуктовой разработкой приложений, а не игровой, по этому это приложение как практика в основном направлении. На данном этапе мне понятно, что работать на таком стеке оно может и закончить его я смогу. Возможно стоит добавить dagger hilt.

Резюме: Кто хочет попробовать - скачайте и пробуйте, игра бесплатная и без рекламы. Кто шарит за разработку - можем продолжать развивать приложение в команде. Кто шарит за лирику - писать сюжетные арки тоже нужны талантливые люди) Написать мне можно на гитхабе в комментариях к проекту, или тут в комментариях. Спасибо всем, кто послушал.

скачать в плеймарет: https://play.google.com/store/apps/details?id=com.pavlovalexey.torpedo
код проекта в открытом доступе: https://github.com/AlexeyJarlax/Visual_Novel_Torpedo_boat_Fury

Показать полностью 4

А заблокируют ли gmail?1

А заблокируют ли gmail? Android, Gmail, Блокировка YouTube, Блокировка, Санкции

Без ютуба кое-как справимся, я вот уже практически полностью мигрировал на сервисы Яндекс, а что если заблокируют сервис gmail? Почтой их не пользуюсь, но все андроид устройства живут на этих аккаунтах.
Как быть, есть ли какое-то решение, можно ли уже как-то заранее подготовиться? Ведь вероятность такая есть, и все к этому стремится.

Показать полностью 1

Узнавать о том, как работают люди других профессий, полезно!

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

ЧИТАТЬ СОВЕТЫ

Мое решение 3-х проблем MVx

Автор текста: Lynnfield

Итак, в прошлый раз я описал три проблемы, которыми, на мой взгляд, страдают все MVx и даже некоторые не MVx архитектуры. Если коротко, то это:

  • проблема остатка — при делении фичи на заявленные компоненты архитектуры остаётся либо «неделимая» часть фичи, либо лишние компоненты архитектуры;

Мое решение 3-х проблем MVx Разработка, Программирование, Android, Timeweb, Алгоритм, Программное обеспечение, Telegram (ссылка), Длиннопост
  • проблема масштабирования — при расширении фичи компоненты архитектуры начинают раздуваться, что усложняет дальнейшую поддержку;

Мое решение 3-х проблем MVx Разработка, Программирование, Android, Timeweb, Алгоритм, Программное обеспечение, Telegram (ссылка), Длиннопост
  • и проблема разрывов логики, когда из-за взаимодействия с UI логика разрывается на части, что тоже не помогает нам делать систему более цельной, предсказуемой и тестируемой.

Мое решение 3-х проблем MVx Разработка, Программирование, Android, Timeweb, Алгоритм, Программное обеспечение, Telegram (ссылка), Длиннопост

Описание проблем это, конечно, хорошо, но вопрос в том, как их решать? Об этом я бы и хотел поразмышлять в этом тексте. Спойлер: когда я нашел решение проблемы разрывов, я понял, что оно может решить и все остальные проблемы.

❯ Проблема остатка (Remainder issue)


Первый вопрос: что делать с остатком? Все просто — взять делитель поменьше, потому что чем меньше делитель, тем меньше остаток. Этому меня еще в школе научили. Но я столкнулся с тем, что это не работает с MVx архитектурами, потому что мой делитель, обычно, это набор определенных компонент, и введение новых — значит изменение архитектуры.

Возможно и вы с этим сталкивались, когда вводили всякие мапперы, делегаты, интеракторы (те, что репозитории репозиториев) и прочее. Помогли ли они мне? Нет. Лучшее решение, что я видел — это Flux- и ELM-like архитектуры, которые заявляют «чистую» функцию как единицу деления логики, но со всеми вытекающими отсюда удобствами и следующими за ними «эффектами».

Но решение проблемы остатка, даже если бы оно у меня было, не помогает мне решить проблему масштабирования.

❯ Проблема масштабирования (Scalability issue)


В прошлый раз я упоминал «интуитивный» подход к решению задачи масштабирования и рассказывал почему он не работает. По крайней мере не у меня.

А какой не интуитивный?

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

Так и в MVx архитектурах: можно было бы попробовать реализовывать доработки отдельно, а уже потом объединять их с существующей фичей, вместо того, чтобы вносить изменения в уже написанные компоненты. Что в прошлом не раз приводило меня к череде переписываний тестов, судорожному протыкиванию приложения на предмет того, что ничего не поменялось, и мольбам о том, чтобы очередной баг-репорт был не по моим изменениям.Но вот что я заметил, ведь именно такой подход, когда мы предпочитаем композицию изменениям, я и мои коллеги используем для Data-слоев. Например, новые источники данных оборачиваются в Репозитории, а потом комбинируются в Интеракторы. Но почему-то чем ближе мы подходим к UI-слою, тем больше начинаем изменять, а не комбинировать.

Чаще всего я вижу эту проблему как вечное переписывание тестов уже существующих компонент, или Presenter, ViewModel, Controller размером со вселенную, который даже трогать страшно, потому что что-то точно развалится.

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

Мое решение 3-х проблем MVx Разработка, Программирование, Android, Timeweb, Алгоритм, Программное обеспечение, Telegram (ссылка), Длиннопост

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

Мое решение 3-х проблем MVx Разработка, Программирование, Android, Timeweb, Алгоритм, Программное обеспечение, Telegram (ссылка), Длиннопост

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

❯ Проблема разрывов (Gaps issue)


И вот тут становится интересно. Все дело в Hello World. Мне все никак не дает покоя вопрос: какая у него архитектура?

Hello world


Я видел примеры Hello World в разных языках, фреймворках и архитектурах (кроме Open GL, конечно же), и у них не было проблем с его реализацией. Если не считать проблемой то, сколько усилий надо приложить, чтобы написать изначальный шаблон. Но, если результат одинаковый, не значит ли это, что разница только в том, сколько обвязок надо написать, чтобы Hello World работал? И нужны ли они? Тогда я стал думать: а что общего у всех этих реализаций Hello World в разных архитектурах? И как-то я пришел к мысли, что скорее всего правильный ответ — Алгоритм. И он до безобразия тривиален.

Мое решение 3-х проблем MVx Разработка, Программирование, Android, Timeweb, Алгоритм, Программное обеспечение, Telegram (ссылка), Длиннопост

И что интересно, у самого алгоритма нигде не написана архитектура в которой он должен быть имплементирован. Но это Hello World. Как я и сказал: он чересчур прост.

Более интересные примеры


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

Мое решение 3-х проблем MVx Разработка, Программирование, Android, Timeweb, Алгоритм, Программное обеспечение, Telegram (ссылка), Длиннопост

А вот еще интересное наблюдение: если мы немного обобщим алгоритм Hello World, отделив show от Hello World, то увидим, что он дважды появляется в алгоритме этого примера.

Все еще слишком просто, правда? Следующий учебный пример — работа со структурами данных. И в самом простом виде — это CRUD плюс “показать все” с хранением в списке (он же List). Этот пример, не очень интересный с точки зрения реализации, интересен тем, что он добавляет в предыдущий алгоритм композицию.

По сути здесь мы первый раз сталкиваемся с тем, что нам надо создать пять независимых программ, а потом объединить их под управлением шестой. А еще эти шесть программ делят между собой один блок памяти — сам список структур. И мне кажется, что это уже напоминает решение одной из наших проблем, не так ли?

Мое решение 3-х проблем MVx Разработка, Программирование, Android, Timeweb, Алгоритм, Программное обеспечение, Telegram (ссылка), Длиннопост

Появление Gaps issue


Но что происходит даже с этими простыми программами, когда мы пытаемся перенести их в UI-среду?

Легче всего Hello World, потому что он просто обрастает кучей компонент, которые помогают ему “жить” в новой среде. Даже не интересно.

А вот Hello %user name% приходится куда сложнее. Беднягу размазывает по компонентам системы или архитектуры: в одном месте мы слушаем ввод имени, в другом показываем приветствие, а в третьем прописываем реакцию на введенное имя.

Я даже боюсь говорить о том, что же происходит с CRUD-примером. В зависимости от того, какой макет нам нарисуют, мы будем писать совершенно разные приложения. Вот представьте, что вас попросили сделать такую программу как несколько разных экранов, а потом попросили переделать так, чтобы это был один экран. С часто используемым подходом к декомпозиции, когда один экран — один набор MVx-компонент, мы получим бессонную ночь переписывания кода, потому что части нашей логики разорваны и раскиданы по всей реализации.

Мое решение 3-х проблем MVx Разработка, Программирование, Android, Timeweb, Алгоритм, Программное обеспечение, Telegram (ссылка), Длиннопост


Но ведь изначально “не было ни единого разрыва”, а алгоритм остался тем же. Почему все стало так плохо?

Причина — асинхронность


На этот вопрос некоторые уже дали ответ в комментариях к предыдущим статье и видео, и я с ними полностью согласен. Причина — асинхронность. И я был искренне удивлен, когда пришел к этому выводу.

Многие, если не все GUI-системы построены вокруг event loop, потому что нам надо одновременно и экран рисовать, и ввод от пользователя слушать. А чтобы сюда добавить еще и наш алгоритм, его придется разделить так, чтобы он хорошо встраивался в этот event loop.

Я уже не говорю о том, что мы вообще-то еще должны взаимодействовать с другими асинхронными системами. Кстати, с ними то, обычно, проблем и не возникает. А почему?

Решение — закрытие разрыва

Мое решение 3-х проблем MVx Разработка, Программирование, Android, Timeweb, Алгоритм, Программное обеспечение, Telegram (ссылка), Длиннопост

Обратим внимание на графикоподобную картинку, на которой я объяснял проблему разрывов в прошлый раз.

Напомню как всё было, и в этот раз уже не буду лукавить: путь нашей логики начинается в каком-то из callback’ов, а не в абстрактном “начале”. По мере выполнения мы продвигаемся все глубже по стеку вызовов, выполняем одну за другой функции, и в самой верхней точке нашего графика мы обращаемся к источнику данных: бэкенду, файлу, какой-то системе хранения. И что здесь обычно находится?

Мое решение 3-х проблем MVx Разработка, Программирование, Android, Timeweb, Алгоритм, Программное обеспечение, Telegram (ссылка), Длиннопост

Обычно это вызов какой-то “асинхронной” функции: корутины, async- или suspend- функции, уж простите мой котлинский, или какой-то функции с callback’ом, или функции возвращающей какой-нибудь Future, Promise или Single.

И вот вопрос: вызывая эту функцию с callback’ом, как часто мы задумываемся, что эта операция может вообще никогда не вернуться в этот callback? Лично я до недавнего времени считал, что управление гарантированно будет передано в наш callback. Не считая случаев “отмены”, конечно же. Но откуда у нас такая гарантия? Возможно все дело в реализации системы? Давайте “заглянем под капот” и посмотрим что же там на самом деле происходит.

Наша функция формирует наш запрос к базе, запрос в сеть или еще что-то. В общем случае формирует какой-то контекст, с помощью которого надо выполнить запрос, и вместе с callback’ом, в который надо вернуть результат, отправляет его на другой поток, и там происходит все выполнение. После завершения выполнения, тот поток вызывает callback, передавая в него результат, что для нас, разработчиков, выглядит как своего рода возврат в точку вызова. Таким образом логика выглядит более цельной, и такого разрыва, как в случае с UI не происходит.

Мое решение 3-х проблем MVx Разработка, Программирование, Android, Timeweb, Алгоритм, Программное обеспечение, Telegram (ссылка), Длиннопост

Так вот вопрос: а почему бы нам не повторить этот же трюк с UI?

На картинке это будет выглядеть как параллельный перенос: мы просто поднимем нашу линию, а вот тут, в нижней точке, вместо того чтобы разрывать логику и отдельно задавать на UI какое-то состояние и callback’и, сделаем функцию, которая отправляет запрос на UI и ждет от него ответа. Таким образом мы закрываем разрыв и теперь наша логика будет выглядеть как единое целое.

Мое решение 3-х проблем MVx Разработка, Программирование, Android, Timeweb, Алгоритм, Программное обеспечение, Telegram (ссылка), Длиннопост

Ничего сложного, мы даже не изобретаем что-то новое, но такой подход поможет нам взаимодействовать с UI, как с любой другой внешней системой, а не как с чем-то особенным. И вот моё видение того, как это могло бы работать и решать проблемы, описанные выше.

❯ Proposal


Давайте писать функции…

Да, может звучать нелогично, тем более, что я уже говорил о том, что это не помогает Flux- и ELM-like архитектурам, но я объясню. Начнем с проблемы остатка.

Влияние на решение проблемы остатка


Добавлю небольшую аналогию с математикой. Как я и говорил «архитектура» — это делитель. А чтобы при делении не оставалось остатка — нам нужно найти наибольший общий делитель. Чем и является функция, на мой взгляд. Чем больше я смотрю на реализации всех наших «архитектур», тем больше я вижу, что все они, по сути, просто один из способов удобнее объединять и специализировать функции (и тут я подразумеваю, что метод класса — это функция, которая иногда неявно принимает дополнительный аргумент).

Дальше лучше — проблема масштабирования.

Решение проблемы масштабирования


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

А что с разрывами?

Решение проблемы разрывов


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

❯ Концепт


Так что же я предлагаю?

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

Мое решение 3-х проблем MVx Разработка, Программирование, Android, Timeweb, Алгоритм, Программное обеспечение, Telegram (ссылка), Длиннопост

Во-вторых, у этой функции (композиции функций) должна быть возможность работать независимо от «сторонних» систем, поэтому я предлагаю вынести ее в свой поток, чтобы у нее была возможность спокойно выполняться, блокироваться при необходимости, параллелиться и тому подобное. Пусть будет “синхронной”. Обычно мне не надо, чтобы логика продолжала свое выполнение, когда она ждет какой-то ресурс. А если такое поведение нужно, то почему-бы его не описать его явно? И назвать бы этот поток Main, но имя уже “занято”. =)

В-третьих, хотя это и самый важный пункт, а у меня видимо есть тенденция оставлять все важное на потом, я предлагаю сосредоточиться на реализации логики приложений, а не экранов и виджетов. Как видите, с таким подходом нет разницы между слоем данных и пользователем. Есть только наша детерминированная логика и внешние системы, которые обмениваются данными через нее. Логика просто ходит между ними и предоставляет им некий контекст для принятия решения и набор возможных действий, а внешние системы в свою очередь “отвечают” нашей логике руководствуясь представленным контекстом. Это похоже на игру в шахматы, где внешние системы — игроки, а логика — доска с фигурами и правила игры.

Мое решение 3-х проблем MVx Разработка, Программирование, Android, Timeweb, Алгоритм, Программное обеспечение, Telegram (ссылка), Длиннопост

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

В конце концов, применив этот концепт, я хочу помочь всем нам проектировать и писать кроссплатформенные приложения в самом широком смысле этого слова: разрабатывая и реализуя end-to-end алгоритмы которые прозрачно перескакивают с бэкенда на фронт и обратно, которые не видят различия между разными видами фронтов, будь то Web, iOS или Android, или разными типами вроде UI, CLI, или TalkBack.

Но пока это только концепт и виденье. Пожалуй пора посмотреть на код, но он будет в следующий раз. А сейчас есть время порефлексировать на эту тему. Дайте этим идеям время перевариться. Прочитайте еще раз. Задайте вопросы. И может вы сможете написать код еще до того, как я опубликую продолжение. Хотите посоревноваться?

Увидимся.


Показать полностью 14

Опрос разработчиков: Вам это нужно ?

Опрос разработчиков: Вам это нужно ? Android разработка, Web-программирование, Принтер, Android

Пишу службу печати под Android (ps402d). Нужно ли для Вас добавить способ отправить на задание принтеру сразу в мой драйвер ? Если да, то какой вариант предпочитаете ?

1) Через startActivity

2) BindService

3) Общаться через ws (вебсокет)

Показать полностью 1

Релиз моей игры!

Это детективная визуальная новелла. На её разработку у меня ушло чуть больше года. Но вот она закончена!

Релиз моей игры! Игры, Разработка, Визуальная новелла, Android, Длиннопост
Релиз моей игры! Игры, Разработка, Визуальная новелла, Android, Длиннопост
Релиз моей игры! Игры, Разработка, Визуальная новелла, Android, Длиннопост
Релиз моей игры! Игры, Разработка, Визуальная новелла, Android, Длиннопост
Релиз моей игры! Игры, Разработка, Визуальная новелла, Android, Длиннопост

Игра называется "Меньше знаешь". Её свободно можно найти в Google play.
https://play.google.com/store/apps/details?id=thelessyouknow...
Описание сюжета игры:

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

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

------------------------------------------------------------------

• Игра бесплатная, но вышла лишь для устройств Android
• Донатов нет
• Монетизации тоже пока нет.
• Игру создавала одна без команды.

Стараюсь пиарить игру как могу. Денег на рекламу пока нет, поэтому всё своими силами.

Показать полностью 4

Кто разбирается в мобильных приложениях, подскажите

Некоторые приложения (типа "Мой налог" или "NetSchool"), когда жмешь вход через Госуслуги, вместо того, чтобы открыть Госуслуги и запросить, например, только смс, открывают форму полной авторизации на Госуслугах, причем, все ручками надо вбивать.
И вот вопрос: ПОЧЕМУ? Может, надо еще в настройках что-то сделать?

Мое первое приложение на android

Всем привет) Вот и я решил написать о своем приложении. Самое интересное никогда не понимал программирование и в школе и в универе. Но сам того не знаю в голову пришла идея попробовать сделать что-то интересное. И вот что получилось 👇👇👇

Мое первое приложение на android Android, Приложение на Android, Android разработка, Kotlin, Видео, Без звука, Вертикальное видео, Длиннопост

От рождения идеи до загрузки в Google Play прошло 3 месяца.

Мое первое приложение на android Android, Приложение на Android, Android разработка, Kotlin, Видео, Без звука, Вертикальное видео, Длиннопост

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

Хотя к этому времени уже написал код который криво но работает по поиску имен из базы. Т.е на пустом экране строка поиска с выводом информации.

Но желание закончить начатое было сильнее. И уже сначала полностью создаю примерный дизайн и основные функции и как они должны работать прямо на блокноте ручкой).

А когда понимаешь что должно быть в конце и писать код стало гораздо интереснее.

А ещё сложнее оказалось сделать аккаунт разработчика в Google Play) Тот ещё квест с потерей денег и времени.

Буду рад критике и за новые идеи.

Ссылка на приложение: https://play.google.com/store/apps/details?id=com.bashkir_ta...

Показать полностью 2 1
Отличная работа, все прочитано!