MVP + Interactors

Учитывая следующий поток:

MVP + Interactors

Я хочу, чтобы методы выполнялись этими потоками:

  • OnClick (по системе): ui
  • OnRefresh (1): пользовательский интерфейс
  • ReadDb (2): рабочий
  • SetData (3): пользовательский интерфейс

Я мог бы добиться этого, сделав ReadDbасинхронный и Ждитеing его, но это заморозило бы поток пользовательского интерфейса.

Можете ли вы придумать подход, который не предполагает реализации Interactors, AsyncTask и т. д.?

Спасибо.


Редактировать

Я ищу элегантное решение, пожалуйста, избегайте использования оберток типа new Handler (Looper.getMainLooper()).post(...), RunOnUiThread в каждом методе View и т. д.

Самый простой подход - использовать taskt и await:

async OnRefresh() {
    data = await m.ReadDb() 
    v.SetData(data)
}

Однако пользовательский интерфейс на await m.ReadDb() зависает. Я думал, что, поскольку OnRefresh возвращает void, он вернется и завершит выполнение родительского метода (OnClick). Затем, как только await будет готов, он запустит v.SetData(d). По какой-то причине я получаю не такой результат.

Зачем его ждать? вы можете выполнить ReadDb async, и как только данные будут загружены, отправьте их в MainThread и выполните v.setData ...

Saba 01.05.2018 12:51

@SabaJafarzadeh Что вы имеете в виду под send it to MainThread?

JonZarate 01.05.2018 14:06

означает запускать его в потоке пользовательского интерфейса. (автор Handler(Looper.gerMainLooper())

Saba 01.05.2018 14:23
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
72
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Что-то вроде этого:

class View {
    IPresenter p;

    void onClick() {
        p.OnRefresh()
    }

    void setData() {

    }
}

class Presenter implements Listener {
    void OnRefresh() {
        // You can do it with newThread or anything that does async
        async (
            m.readDB()
        )
    }

    void onComplete(Data data) {
        // or you can put it on Model class.
        new Handler(Looper.getMainLooper()).post(() -> {
            // this will be run on ui (or main) thread.
            v.setData(data);
        })
    }
}

class Model {

    Listener lstr;

    void readDB() {
        // read data..

        // completed
        lstr.onComplete(data)
    }
}

interface Listener {
    void onComplete(Data data)
}

Вы также можете добавить onFailure () и другие методы, также RxJava делает это намного проще, взгляните на это.

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

Спасибо, Саба, к сожалению, мне такой подход не нравится. Я не хочу иметь Listeners для каждого звонка, который я делаю к Model, и не хочу везде использовать шаблонный код new Handler(Looper.getMainLooper()).post((). Я объясню это в посте и для других людей.

JonZarate 01.05.2018 14:45
Ответ принят как подходящий

На самом деле мой подход был правильным, но реализация неправильная. Я ожидал, что await m.ReadDb() будет запущен в рабочем потоке, но этого не произошло. Причина этого в том, что мне пришлось явно запросить это с Task.Run и await:

OnRefresh() 
{
    var d = await Task.Run (() => m.ReadDb());
    v.SetData(d)
}

Простая запись await не создает новый поток, поэтому пользовательский интерфейс был заблокирован.

Проверьте мой другой вопрос в SO, где мне на это указали.

Другие вопросы по теме