Pull to refresh
10
0
Евгений Попович @Evgenij_Popovich

User

Send message

Спасибо за статью, как всегда очень основательно.

Вы не рассматривали возможность использовать мультибиндинги из какого-нибудь DI фреймворка или Manual DI? App ведь знает о всех модулях и может строить общий DI граф в котором может быть какая-то коллекция интерфейсов нужного типа.

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

Работа титаническая. Manual di через делегаты не рассматривали как альтернативу даггеру?

https://youtu.be/wrF4ZxhBJ-M?si=jVDcI5Ztnojk07Qb

У StateFlow есть потокобезопасный метод update. Это я к тому, что нет необходимости синхронизации в вашей реализации CountdownBarrier

Спасибо за статью. Сложная тема, легко себе в ногу стрельнуть. Поэтому в своем коде стараюсь вообще не выкидывать и не ловить исключения. Использую kotlin.Result как альтернативу.

Спасибо за статью. Можете, пожалуйста, сказать какие преимущества вы видите для себя от использования dsl тут вместо более простых в реализации и надёжных в плане контроля за обязательными параметрами фабрик? Также в фабриках остается возможность задать дефолтные значения для аргументов.

Ахах, один в один, предложили ровно 75% от того, что я просил. Похоже это у них такая стратегия (давно на рынок, видно, не заглядывали). В куче с трояном opswat - "супер" предложение

Работал продолжительное время в стартапе Drill City (к сожалению, еле живому на текущий момент). Так вот, у нас была довольно интересная комплексная методика, которая позволяла говорить даже стесняющимся своего произношения людям.


  1. На основе интервальных повторений можно было учить новые фразы. Проверка материала осуществлялась на основе распознавания речи от Гугл или на основе аудиозаписи, где вы сами вольны были оценить правильность ответа. Чем чаще правильно отвечали, тем реже фраза повторялась и наоборот.


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


  3. Можно было смотреть фильмы по схожей схеме отрывками: когда смотришь на иностранном замедленно, потом на родном, потом вновь на иностранном но уже с нормальной скоростью. Также поддерживались параллельные субтитры на 2-х языках



Хз, почему не взлетело. До последнего верил, что взлетит. Думаю, дело в ограниченном маркетинговом бюджете

Спасибо за статью

Заметил, что во многих местах вы используете промежуточный BehaviorSubject вместо использования соответствующего метода Observable.create

Также, имхо, в методах типа createSimpleDialog логичнее смотрится результатом объект типа Single или Maybe
а сейчас те же 2 литра продают уже за 25-30 баксов

Это какие-то спекулянты. В Украине регулярно покупаю 60% перекись по цене 1-1.5 доллара за кг для дезинфекции бассейна летом.

> Я не совсем понял ваш комментарий про EventBus, если распишите подробнее свою мысль, постараюсь ответить.

Имел в виду, что концепция input/output потоков напоминает шаблон EventBus. Но у вас отличие, что не все компоненты слушают абсолютно все события от любых компонентов, а только отфильтрованные с помощью заданных вручную биндингов.

Спасибо за пример. Сам я использую местами похожий на ваше решение «велосипед» основанный на RxJava, позволяющий как отправлять события так и получать колбеки на них. Поэтому было интересно, как вы решили эту проблему.
У меня же в Output сваливаются не события, а нечто вроде Pair<Event, Maybe>, где первый аргумент изначальное событие а второй результат его обработки. После результат передается в том место, откуда поступил запрос. Это позволяет делать цепочки вида
class Login extends RequestMessage<Boolean>{}
....
request(new Login())
.flatMap(result -> result ?
     request(new Operation1()) :
     request(new Operation2())
....
Спасибо за статью.

Похоже, у вас получился EventBus с ручной маршрутизацией. Как вы решаете вопрос, если какому-то событию нужен колбек?

Уже несколько лет разрабатываем приложение "drill.city" под андроид, в котором основной акцент идет на обучение голосом (можно даже с выключенным экраном заниматься). В основе лежит распознавание речи от Гугл с некоторыми усовершенствованиями. Приложение пока не рекламируется, поэтому вы о нем не слышали, скорее всего.


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

… рассказывающий о торможении корабля в атмосфере

У меня во время прослушивания этого трека, почему то, всегда возникают такие ассоциации

Для себя проблему наследования решил выделением абстрактного билдера с дженерик аргументами. Выглядит «слегка» монстроуозно, но работает
Код
@Test public void testBuilders(){
    User user = new User.Builder()
            .firstName("Sergei")
            .lastName("Egorov")
            .build();
    assertEquals("Sergei", user.firstName);
    assertEquals("Egorov", user.lastName);

    User userCopy = new User.Builder(user)
            .build();
    assertEquals("Sergei", userCopy.firstName);
    assertEquals("Egorov", userCopy.lastName);

    RussianUser russianUser = new RussianUser.Builder()
            .firstName("Sergei")
            .patronymic("Valeryevich")
            .lastName("Egorov")
            .build();
    assertEquals("Sergei", russianUser.firstName);
    assertEquals("Valeryevich", russianUser.patronymic);
    assertEquals("Egorov", russianUser.lastName);

    RussianUser russianUserCopy = new RussianUser.Builder(russianUser)
            .build();
    assertEquals("Sergei", russianUserCopy.firstName);
    assertEquals("Valeryevich", russianUserCopy.patronymic);
    assertEquals("Egorov", russianUserCopy.lastName);
}

public static class User {

    public final String firstName;

    public final String lastName;

    User(AbstractBuilder builder) {
        firstName = builder.firstName;
        lastName = builder.lastName;
    }

    public static class Builder extends AbstractBuilder<Builder, User> {

        public Builder() {
        }

        public Builder(User item) {
            super(item);
        }

        @Override public User build() {
            return new User(this);
        }
    }

    public static abstract class AbstractBuilder<
            BUILDER extends AbstractBuilder,
            RETURN extends User> {

        String firstName;
        String lastName;

        public AbstractBuilder() {
        }

        public AbstractBuilder(RETURN item) {
            firstName(item.firstName);
            lastName(item.lastName);
        }

        BUILDER firstName(String value) {
            this.firstName = value;
            return getBuilder();
        }

        BUILDER lastName(String value) {
            this.lastName = value;
            return getBuilder();
        }

        public BUILDER getBuilder() {
            return (BUILDER) this;
        }

        public abstract RETURN build();
    }
}

public static class RussianUser extends User {
    final String patronymic;

    RussianUser(AbstractBuilder builder) {
        super(builder);
        patronymic = builder.patronymic;
    }

    public static class Builder extends AbstractBuilder<Builder, RussianUser> {

        public Builder() {
        }

        public Builder(RussianUser item) {
            super(item);
        }

        @Override public RussianUser build() {
            return new RussianUser(this);
        }
    }

    public static abstract class AbstractBuilder<
            BUILDER extends AbstractBuilder,
            RETURN extends RussianUser>
            extends User.AbstractBuilder<BUILDER, RETURN> {
        String patronymic;

        public AbstractBuilder() {
        }

        public AbstractBuilder(RETURN item) {
            super(item);
            patronymic(item.patronymic);
        }

        BUILDER patronymic(String value) {
            this.patronymic = value;
            return getBuilder();
        }
    }
}

Спасибо. На RxJava без вложенных вызовов так, пожалуй, не напишешь
Не могли бы Вы, пожалуйста, справедливости ради показать как будет выглядеть код с аналогичными сайд эффектами на корутинах?
На 2-м шаге, там где про рефакторинг, показав обновленный код на корутинах, Вы, как мне кажется, несколько слукавили. Ведь на RxJava тоже можно написать так:

Observable.zip(observable1, observable2, observable3, 
(t1, t2, t3) -> new Result(t1, t2, t3))
.subscribe(r -> /* handle result */, () -> /*handle completion*/,  e -> /* handle errors */)
1
23 ...

Information

Rating
4,256-th
Location
Мукачево, Закарпатская обл., Украина
Date of birth
Registered
Activity